#include <stdio.h>
#include <stdlib.h>
typedef struct __test {
int i;
void (*echo_fun)(struct __test *p);
}Test;
void __register(Test *p) {
p->i = 1;
p->echo_fun(p);
}
static void __printf(Test *p) {
printf("i = %dn", p->i);
}
//这种 ".成员"的赋值方式为c99标准
static Test config = {
.i = 0,
.echo_fun = __printf,
};
//加载动态库的自动初始化函数
void _init(void) {
printf("initn");
__register(&config);
}
main函数
#include <stdlib.h>
#include <dlfcn.h>
#include <stdio.h>
int main(void) {
void *handle = NULL;
char *myso = "./mylib.so";
if((handle = dlopen(myso, RTLD_NOW)) == NULL) {
printf("dlopen - %sn", dlerror());
exit(-1);
}
return 0;
}
主程序编译: gcc test.c -o test -ldl -rdynamic
动态库编译: gcc -shared -fPIC -nostartfiles -o mylib.so mylib.c
主程序通过dlopen()加载一个.so的动态库文件, 然后动态库会自动运行 _init() 初始化函数, 初始化函数打印一个提示信息, 然后调用主程序的注册函数给结构体重新赋值, 然后调用结构体的函数指针, 打印该结构体的值. 这样就充分的达到了主程序和动态库的函数相互调用和指针的相互传递.
gcc参数 -rdynamic 用来通知链接器将所有符号添加到动态符号表中(目的是能够通过使用 dlopen 来实现向后跟踪).
gcc参数 -fPIC 作用: 当使用.so等类的库时,当遇到多个可执行文件共用这一个库时, 在内存中,这个库就不会被复制多份,让每个可执行文件一对一的使用,而是让多个可执行文件指向一个库文件,达到共用. 宗旨:节省了内存空间,提高了空间利用率。
示例2
//hello.c
#include <sys/types.h>
#include <signal.h>
#include <stdio.h>
#include <unistd.h>
#include "hello.h"
int GetValue(char *pszVal)
{
int retval = -1;
if (pszVal)
retval = sprintf(pszVal, "%s", "123456");
printf("%s, %d, pszVer = %s\n", __FUNCTION__, __LINE__, pszVal);
return retval;
}
int PrintfHello()
{
int retval = -1;
printf("%s, %d, hello everyone\n", __FUNCTION__, __LINE__);
return 0;
}
const hello_ST_API Hello = {
.module = "hello",
GetValue,
PrintfHello,
};
gcc -fPIC hello.c -c生成hello.o
gcc -shared -o hello.so hello.o 生成hello.so
#include <sys/types.h>
#include <signal.h>
#include <stdio.h>
#include <unistd.h>
#include <dlfcn.h>
#include "hello.h"
int main(int argc, char **argv)
{
hello_ST_API *hello;
int i = 0;
void *handle;
char psValue[20] = {0};
handle = dlopen("/home/test/dl-api/hello.so", RTLD_LAZY);
if (! handle) {
printf("%s,%d, NULL == handle\n", __FUNCTION__, __LINE__);
return -1;
}
dlerror();
hello = dlsym(handle, "Hello");
if (!hello) {
printf("%s,%d, NULL == handle\n", __FUNCTION__, __LINE__);
return -1;
}
if (hello && hello->PrintfHello)
i = hello->PrintfHello();
printf("%s, %d, i = %d\n", __FUNCTION__, __LINE__, i);
if (hello && hello->GetValue)
i = hello->GetValue(psValue);
if (hello && hello->module)
printf("%s, %d, module = %s\n", __FUNCTION__, __LINE__, hello->module);
dlclose(handle);
return 0;
}
gcc -o test hello_dlopen.c -ldl
执行结果
PrintfHello, 27, hello everyone
main, 36, i = 0
GetValue, 19, pszVer = 123456
main, 42, module = hello