因此,我正在尝试运行以下示例。
header.h
extern "C" {
void registerfunc();
};
main.cpp
#include "header.h"
#include <dlfcn.h>
#include <iostream>
using namespace std;
typedef void (*register_func)();
void registerfunc() {
cout << "register func has been called" << endl;
}
int main() {
void* lib_handle = dlopen("./test/test.so", RTLD_NOW | RTLD_GLOBAL);
if(lib_handle == NULL){
cout << "no such lib:" << dlerror() <<endl;
return 0;
}
register_func reg = (register_func)dlsym(lib_handle, "test");
if(reg == NULL){
cout << "Cannot load symbol" << dlerror() << endl;;
} else {
reg();
}
return 0;
}
它是用以下生成文件编译的
all:
g++ main.cpp -ldl
然后,我想使用我自己的so中的registerfunc,它是以以下方式编写的:
main.h:
extern "C"
{
void test();
};
main.cpp
#include "main.h"
#include "../header.h"
void test() {
registerfunc();
}
Makefile:
all:
g++ main.cpp -fPIC -shared -o test.so
当我以这种方式编译它并运行a.out(第一个main的输出)时,我得到:
no such lib: ./test/test.so: undefined symbol: registerfunc
但是,如果我使用以下命令编译a.out和test.so:
a.out -> g++ -g -fPIC -shared main.cpp -ldl
test.so -> g++ -g main.cpp -fPIC -shared -o test.so ../a.out
然后我得到了一个分段错误与以下回溯(gdb-ex-runa.out):
0x0000000000000001 in ?? ()
这让我有点困惑,不知道如何让test.so调用被调用者定义的东西。你能帮忙吗?
这里至少有三个单独的问题:
-
较小的一个是,您有两个名为
main.cpp
的文件,不完全清楚哪个命令指的是问题中的哪个文件。 -
更大的问题是,您希望
test.so
在a.out中绑定到registerfunc
,但该函数不会从a.out
导出,除非参与链接的某个共享库引用了该函数,或您使用-Wl,--export-dynamic
链接(导出所有函数)。这才是真正的解决方案。您可以使用以下命令查看从
a.out
导出的功能:nm -D a.out | grep ' T '
-
最后,当你这样做时:
a.out -> g++ -g -fPIC -shared main.cpp -ldl
您实际上是在创建一个共享库(名为
a.out
),而不是一个可执行文件。将这样一个共享库当作可执行文件来运行会导致您所观察到的崩溃。