美文网首页
C/C++运行时导入动态库

C/C++运行时导入动态库

作者: 突击手平头哥 | 来源:发表于2020-04-10 21:38 被阅读0次

运行时导入动态库

动态库

  • 在Linux下的动态库值得通常是.so文件, windows下的动态库通常时.dll文件

  • 动态库与静态库相比, 通常在编译时和运行时都需要该动态库

  • 在编译时可以指定-l来链接动态库, 在运行调用函数时则会自动调用动态库中的函数

模块化/插件化

  在很多工程中视功能分为多个模块, 而且可以动态的指定加载那些模块甚至于实时卸载模块, 这又是怎么实现的呢?

dlopen族函数

#include <dlfcn.h>

void *dlopen(const char *filename, int flags);

void *dlsym(void *handle, const char *symbol);

int dlclose(void *handle);
  • dlopen: 动态导入指定动态库

    • flags可以指定一些FLAG, 通常为RTLD_NOW即可
  • dlsym: 通过dlopen获得的句柄以及符号名字来获得指定函数的句柄

  • dlclose: 关闭dlopen获得的句柄

  • 编译时需要指定动态库-ldl

windows下

#define dlopen(p, f)    LoadLibraryA(p)
#define dlsym(h, n)     GetProcAddress(h, n)
#define dlclose(h)      FreeLibrary(h)

代码实例

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <dlfcn.h>
#include <assert.h>
 
typedef int (*fun)(int, int);
 
int main() {
    void *f = dlopen("./libadd.so", RTLD_LAZY);

    assert(f);

    fun add = (fun)dlsym(f, "add");

    assert(add);

    printf("add: %d\n", add(1, 2));

    dlclose(f);

    //printf("add: %d\n", add(1, 2));

    return 0;
}

//编译命令
gcc test.cpp -ldl

动态库代码

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>


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

//编译命令
gcc -fPIC -shared add.c -o libadd.so

nm命令

bogon:~/winsf$ nm libadd.so
00003f28 d _DYNAMIC
00004000 d _GLOBAL_OFFSET_TABLE_
         w _ITM_deregisterTMCloneTable
         w _ITM_registerTMCloneTable
000020b0 r __FRAME_END__
00002000 r __GNU_EH_FRAME_HDR
00004010 d __TMC_END__
         w __cxa_finalize@@GLIBC_2.1.3
000010e0 t __do_global_dtors_aux
00003f24 t __do_global_dtors_aux_fini_array_entry
0000400c d __dso_handle
00003f20 t __frame_dummy_init_array_entry
         w __gmon_start__
00001150 t __x86.get_pc_thunk.ax
00001040 t __x86.get_pc_thunk.bx
00001135 t __x86.get_pc_thunk.dx
00001154 t _fini
00001000 t _init
00001139 T add
00004010 b completed.6886
00001050 t deregister_tm_clones
00001130 t frame_dummy
00001090 t register_tm_clones
  • 可以看到上面的add函数符号, 当dlopen成功但是dlsym失败时可以通过nm命令看一下函数的符号到底是什么

  • 注意的是c/cpp编译出的符号是不一样的, 需要额外注意(C++有重载)

  • 注意: 我之前用的cpp文件、gcc命令、debian环境, 发现编译出的符号是: _Z3addii;

问题注意

  • 动态库符号问题

  • 当使用了dlclose后, 之前获得的句柄也不能再用了; 会出现段错误

相关文章

网友评论

      本文标题:C/C++运行时导入动态库

      本文链接:https://www.haomeiwen.com/subject/kwkjmhtx.html