主要介绍了在c/c++中如何使用dynamic link来动态加载.so文件以及涉及到的一些重要环境变量。
dynamic link 与 static link 这一篇  对于shared library 和 static library 说明的比较透彻,详细的内容看原文,大致上static library使用.a的后缀,在使用static library的时候,code直接被link到binary的文件中。而使用shared library则是.so结尾 在程序run的时候才会去寻找实际的.so文件的位置(这个.so文件本身就是一个二进制文件)。
使用ldd <binaryfile> 可以查找到当前的这个 binary file 在动态链接的时候都链接到了哪些.so文件以及其具体的路径 这个可以用来debug动态链接时候的问题,有的时候没有链接到一个动态库上,比如之前的安装mpi4py的问题,当时想通过python传一个mpi的communicator给c的code,只有mpi4py和本身的c code 使用了一个mpi的动态链接库的时候 这个思路才可能实现 但有的时候安装环境可能有问题 导致mpi4py所链接的mpi library和 c code 所链接的library 不是一个 具体的问题和详细信息可以参考这个  以及 这个 。
使用gcc进行dynamic link dynamic link就是在运行的时候动态地链接所需要的代码库,在Linux中,动态链接库通常是被封装成为.so的形式。下面是一个具体的例子:
比如caculate.c文件中放置了好多函数,我们希望通过动态连接的方式使用这些函数:
#include "stdio.h"  int add(int a, int b) {     return (a + b); }  int sub(int a, int b) {     return (a - b); }  int mul(int a, int b) {     return (a * b); }  int div(int a, int b) {     return (a / b); }  void action() {     printf("test action func\n"); } 
使用如下命令编译:
gcc -fPIC -shared caculate.c -o libcaculate.so 
之后可以使用nm命令查看 .so文件中的内容
$ nm libcaculate.so 0000000000000f40 T _action 0000000000000ec0 T _add 0000000000000f20 T _div 0000000000000f00 T _mul                  U _printf 0000000000000ee0 T _sub                  U dyld_stub_binder 
之后可以加载这个动态链接库并且根据外部变量导入指定的函数
#include <stdio.h> #include <stdlib.h> #include <dlfcn.h> //动态链接库路径 #define LIB_CACULATE_PATH "./caculatelib/libcaculate.so" //函数指针 typedef  int (*CAC_FUNC)(int, int); typedef  void (*ACT_FUNC)(); int main() {     void *handle;     char *error;     CAC_FUNC cac_func = NULL;     //打开动态链接库     handle = dlopen(LIB_CACULATE_PATH, RTLD_LAZY);     if (!handle)     {         fprintf(stderr, "%s\n", dlerror());         exit(EXIT_FAILURE);     }     //清除之前存在的错误     dlerror();     //获取一个函数     *(void **)(&cac_func) = dlsym(handle, "add");     if ((error = dlerror()) != NULL)     {         fprintf(stderr, "%s\n", error);         exit(EXIT_FAILURE);     }     printf("add: %d\n", (*cac_func)(2, 7));     cac_func = (CAC_FUNC)dlsym(handle, "sub");     printf("sub: %d\n", cac_func(9, 2));     cac_func = (CAC_FUNC)dlsym(handle, "mul");     printf("mul: %d\n", cac_func(3, 2));     cac_func = (CAC_FUNC)dlsym(handle, "div");     printf("div: %d\n", cac_func(8, 2));     ACT_FUNC act_func = NULL;     act_func = (ACT_FUNC)dlsym(handle, "action");     act_func();     //关闭动态链接库     dlclose(handle);     exit(EXIT_SUCCESS); } 
具体编译的方式如下:
gcc -rdynamic -o main main.c -ldl 
使用g++进行dynamic link 如果使用g++对.cpp文件进行dynamic link,具体可以参考这个 ,由于c++有name mangling的作用,需要使用extern C来对.so文件进行标记。
比如下面源文件直接进行编译g++ -fPIC -shared add.cpp -o add.so时候再使用nm查看
#include <vector> using namespace std; int add(int c) {     vector<int> v;     int i;     int sum = 0;     for (i = 0; i < c; i++)     {         sum = sum + i;     }     return sum; } 
得到如下的结果:
0000000000000ac0 T __Z3addi 0000000000000d50 t __ZNSt3__113__vector_baseIiNS_9allocatorIiEEED2Ev 0000000000000d10 t __ZNSt3__16vectorIiNS_9allocatorIiEEED1Ev 0000000000000d30 t __ZNSt3__16vectorIiNS_9allocatorIiEEED2Ev                  U __ZdlPv                  U dyld_stub_binder 
由于函数的名字被加上了一些字符,所以动态链接的时候会找不到对应的函数。如果加上extern C再进行编译:
#include <vector> using namespace std; extern "C" int add(int c) {     vector<int> v;     int i;     int sum = 0;     for (i = 0; i < c; i++)     {         sum = sum + i;     }     return sum; } 
使用mn查看之后结果如下:
$ nm add.so 0000000000000d50 t __ZNSt3__113__vector_baseIiNS_9allocatorIiEEED2Ev 0000000000000d10 t __ZNSt3__16vectorIiNS_9allocatorIiEEED1Ev 0000000000000d30 t __ZNSt3__16vectorIiNS_9allocatorIiEEED2Ev                  U __ZdlPv 0000000000000ac0 T _add                  U dyld_stub_binder 
main函数也可以写成.cpp的形式使用g++进行编译:
#include <stdlib.h> #include <stdio.h> #include <dlfcn.h> typedef int (*add_func_ptr)(int);     int main(int argc, char **argv) {     void *handle;     double (*cosine)(double);     char *error;     handle = dlopen("./add.so", RTLD_LAZY);     if (!handle)     {         fputs(dlerror(), stderr);         exit(1);     }     add_func_ptr addfun;     addfun = (add_func_ptr)dlsym(handle, "add");     if ((error = dlerror()) != NULL)     {         fputs(error, stderr);         exit(1);     }     printf("%d\n", (*addfun)(5));     dlclose(handle); } 
参考资料 dynamic link的example
https://medium.com/@LeeJulija/dynamic-and-static-libraries-in-c-bcab492a8da 
https://www.cprogramming.com/tutorial/shared-libraries-linux-gcc.html 
基于c的 dynamic link 的例子
https://www.cnblogs.com/Anker/p/3746802.html 
基于c++的dynamic link 的例子 回答里有许多比较好的Link
https://stackoverflow.com/questions/49187610/dynamic-link-with-dlopen-symbol-not-found?noredirect=1#comment85380797_49187610 
http://tldp.org/HOWTO/C++-dlopen/