dlopen高能操作

#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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值