美文网首页
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