动态链接库的动态加载


#include <stdio.h>
#include <dlfcn.h>


int main(void) {

    // 使用动态加载的编译时必须链接dl库(-ldl),因为动态加载的各种方法都在dl库中
    // gcc main.c -o test -ldl

    /* 获取错误信息 char * dlerror(void)
    * 获取在打开、关闭、使用动态库时发生的错误
    * 有错误返回字符串指针,没有错误返回NULL
    * */

    /* 加载动态库 void * dlopen(const char * __path, int __mode)
     * __path 动态库的路径,如果只给文件名不带路径,则根据LD_LIBRARY_PATH环境变量搜索动态库
     * __mode 加载方式
     *          RTLD_LAZY 延迟加载
     *          RTLD_NOW  立即加载
     * 加载成功返回动态库句柄,失败返回NULL
     * */
    void *handler = dlopen("libmath.so", RTLD_LAZY);
    if (handler == NULL) {
        fprintf(stderr, "dlopen:%s\n", dlerror());
    }

    /* 取动态链接库的符号 void * dlsym(void * __handle, const char * __symbol)
     * __handle 动态库的句柄
     * __symbol 符号(函数名、变量名、结构体名....)
     * 加载成功符号地址,失败返回NULL
     * */
    int (*p_add)(int, int) = dlsym(handler, "add");
    if (p_add == NULL) {
        fprintf(stderr, "dlsym:add:%s\n", dlerror());
    }
    int (*p_sub)(int, int) = dlsym(handler, "sub");
    if (p_add == NULL) {
        fprintf(stderr, "dlsym:sub:%s\n", dlerror());
    }
    void (*p_show)(int, char, int, int (*)(int, int)) = dlsym(handler, "show");
    if (p_show == NULL) {
        fprintf(stderr, "dlsym:show:%s\n", dlerror());
    }
    int a = 10, b = 20;
    p_show(a, '+', b, p_add);
    p_show(a, '-', b, p_sub);
    /* 卸载动态库 int dlclose(void * __handle)
     * __handle 动态库的句柄
     * 卸载成功返回0,失败返回非零
     * 卸载动态库之后,动态库不一定会立即从内存中删除,因为其他程序也许还在使用动态库,但是当前程序通过dlopen获取到的句柄会立即失效
     *
     * */
    if (dlclose(handler)) {
        fprintf(stderr, "dlclose:%s\n", dlerror());
    }


    return 0;
}

posted on 2023-02-07 20:39  信奉上帝的小和尚  阅读(106)  评论(0编辑  收藏  举报

导航