void* dlopen(const char* filepath, int mode)
1.0、参考
1.1、此函数的作用

加载动态库

1.2、参数说明

int mode只能使用下面2

说明
RTLD_NOWresolve all undefined symbols before dlopen() returns and fail if this cannot be done
RTLD_LAZYresolve undefined symbols as code from the dynamic library is executed

const char* filepath用于指定要加载的动态库的路径。

const char* filepath中如果含有/,表明该该路径是相对路径绝对路径,这是就用该路径加载动态库。

const char* filepath中如果不含有/,表明它只是个文件名,这时候,就要进行搜索。至于如何搜索, 由于不同的操作系统使用了不同的loader,搜索的逻辑不尽相同。但都会去LD_LIBRARY_PATH环境变量指定的路径中搜索。

操作系统loader参考
GNU/Linux
/lib/ld-liunx.so.N
/lib64/ld-linux-x86-64.so.N
BSD-based
macOS/usr/lib/dyld
1.3、返回值说明

若成功,则返回非NULL

若失败,则返回NULL

1.4、使用示例

step1、编写一个C源程序add.c,其内容如下

int add(int a, int b) {
    return a + b;
}

step2、使用gcc命令将add.c编译为动态库

gcc -shared -fPIC -o libadd.so add.c

step3、编写一个C源程序main.c,其内容如下

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

int main(int argc, char* argv[]) {
    if (1 == argc) {
        perror("please provide a library path");
        return 1;
    }

    void* handle = dlopen(argc[1], RTLD_LAZY);
    if (NULL == handle) {
        printf("load %s error, %s\n", argc[1], dlerror());
        return 1;
    }
    printf("load %s success.\n", argc[1]);

    int (*add)(int a, int b);
    add = dlsym(handle, "add");
    int value = add(2, 3);
    printf("add(2, 3) = %d\n", value);

    int statusCode = dlclose(handle);
    printf("unload %s %s!\n", argc[1], statusCode ? "failed" : "success");
    return statusCode;
}

step4、使用gcc命令将mian.c编译为可执行文件

gcc -o main main.c

step5、运行main可执行文件

./main libadd.so

运行结果如下:

load libadd.so success.
add(2, 3) = 5
unload libadd.so success.

注意:这种加载动态库的方式,不需要我们在编译的时候进行链接用到的动态库。 相比于动态链接,这种动态加载更灵活。

source code on GitHub