dlopen系列函数

包含的头文件:

#include <dlfcn.h>

使用的函数有以下4个:

1) void * dlopen( const char * pathname, int mode)
参数pathname: 动态库so名称

参数mode 打开方式,有以下选项

  RTLD_DEEPBIND -- 动态库里的函数优先调用本动态库的符号,优先级甚至高于LD_PRELOAD

  RTLD_LAZY -- 等有需要时才解析出符号,所以如果有未定义的符号,在没调用之前也不执行解析
     RTLD_NOW -- 在dlopen返回前,解析出所有的未定义符号,如果解析不出来,返回NULL
     RTLD_GLOBAL 动态库中符号表全局打开,因此符号可被其后打开的其它库重定位

     RTLD_LOCAL  与RTLD_GLOBAL作用相反,动态库中符号表非全局打开,定义的符号不能被其后打开的其它库重定位

返回值:
  打开错误返回NULL
  成功,返回库引用

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

参数handle: 动态库应用或者RTLD_NEXT(在当前库之后load进来的动态库中寻找第一次出现的符号)

参数symbol: 符号名称

返回值:符号函数指针

3) int dlclose (void *handle)

关闭指定句柄的动态链接库

4) char* dlerror();

返回值:返回加载失败的报错信息

 

 

实例:

plugin.h头文件中定义接口

#ifndef __PLUGIN_H__
#define __PLUGIN_H__
#include "stdio.h"
class IPlugin
{
public:
  virtual void print()=0;

};
#endif

main.cpp

#include "plugin.h"
#include <dlfcn.h>
#include <stdlib.h>
#include <stdio.h>
typedef IPlugin* (*func)();
int main()
{
    
    void* handle = dlopen("/home/hongrui/work/dlopen/libplugin.so", RTLD_NOW);
    
    if (!handle)
    {
        printf("dlopen:%s\n",dlerror());
        return -1;
    }
    func getInterface = (func)dlsym(handle, "getInterface");
    if (getInterface == NULL)
    {
        printf("dlsym:%s\n", dlerror());
        return -1;
    }
    IPlugin* plugin =  getInterface();
    plugin->print();
   dlclose(handle);
return 0; }

编译main.cpp 生成可执行文件

  g++ main.cpp -o main -ldl

plugin.cpp是动态库cpp

#include "plugin.h"
#include "stdio.h"
class CPlugin : public IPlugin
{
public:
    CPlugin() {}
    virtual ~CPlugin(){}
    virtual void print()
    {
        printf("this is plugin\n");
    }
};

extern "C" __attribute__ ((visibility("default"))) IPlugin* getInterface()
{
    return new CPlugin;
}

编译plguin.cpp生成动态库libplugin.so

  

g++ -fvisibility=hidden -fpic -shared  plugin.cpp -o libplugin.so -ldl

 

posted @ 2022-03-20 21:23  ho966  阅读(1056)  评论(0编辑  收藏  举报