我正在实现一个从.so文件加载插件的API。要加载它我使用dlsym()函数。为了检查它是否有效,我已经实现了一个测试插件(下面)并且为了简单起见我只加载“初始化”功能。要编译我的代码,我首先使用以下命令创建.so文件:
g++ -Wall -shared -rdynamic -fPIC plugin_test.cpp -o plugin_test.so
之后我按如下方式运行plugin_manager.cpp:
g++ plugin_manager.cpp -o -plugin_manager.o -ldl
但是在运行a.out并输入正确的文件名后,我收到一条错误,我无法加载.so文件。有没有人知道如何解决这个问题?
plugin_manager.cpp
#include <dlfcn.h>
#include <stdio.h>
#include <stdlib.h>
#include <string>
#include <iostream>
#include "plugin_interface.h"
using namespace std;
//typedef void (*test_function)(void);
int main(void) {
const char *error;
void *module;
//test_function initialize_test;
//void (*initialize_test) (void);
//test_function analyze_test;
//test_function finalize_test;
//load the DL library
string filename;
cout << "File :: " << endl;
cin >> filename;
module = dlopen(filename.c_str(), RTLD_LAZY);
if (!module) {
fprintf(stderr, "ERROR! Couldn't load library: %s\n",
dlerror());
exit(1);
}
//get and check symbol
dlerror();
initialize_f* initialize_function = (initialize_f*) dlsym(module, "initialize");
if ((error = dlerror())) {
fprintf(stderr, "ERROR %s\n", error);
exit(1);
}
//create instance of the class
PluginInterface* plugin = initialize_function();
//use the class
plugin->initialize();
//call "initialize" function from the test plug-in
//(*initialize_test)();
dlclose(module); //close the DL library
return 0;
}
plugin_interface.h
#ifndef PLUGIN_INTERFACE_H_INCLUDED
#define PLUGIN_INTERFACE_H_INCLUDED
class PluginInterface{
public:
virtual void initialize() = 0;
virtual void analyze() = 0;
virtual void finalize() = 0;
};
//Definition of the pointer
typedef PluginInterface* initialize_f();
#endif // PLUGIN_INTERFACE_H_INCLUDED
test_plugin.cpp
#include <iostream>
#include "plugin_interface.h"
using namespace std;
class bbb :public PluginInterface {
public:
virtual void initialize(){
cout << "Initialization";
}
void analyze(){
cout << "Analysis";
}
void finalize(){
cout << "Finalization";
}
};
//The functions we load must be qualified as extern "C" to avoid the symbol name being mangled
extern "C" PluginInterface* initialize(){
return new bbb();
}
int main()
{
//bbb* a = maker();
//a->initialize();
//Creating an instance and calling the "initialize" function with in
PluginInterface* p = initialize();
p->initialize();
return 0;
}
答案 0 :(得分:2)
仔细阅读 并多次阅读dlopen(3)手册页。
当flle路径不包含任何/
时,会发生某些特定处理。
您应dlopen
./foo.so
之类的路径(否则在.
环境变量的末尾添加LD_LIBRARY_PATH
,但这可能会带来安全风险,所以我不喜欢建议这样做)
(始终针对NULL
对dlopen
和dlsym
函数调用进行测试,并在失败时显示dlerror()
g++ -Wall -g plugin_manager.cpp -o -plugin_manager -ldl
不要提及plugin_manager.o