所以,我有一个以下的例子,我正试图运行。
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;
}
使用以下makefile编译它
all:
g++ main.cpp -ldl
然后,我想使用我自己的registerfunc,这是用以下方式编写的:
main.h:
extern "C"
{
void test();
};
的main.cpp
#include "main.h"
#include "../header.h"
void test() {
registerfunc();
}
生成文件:
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 run a.out):
0x0000000000000001 in ?? ()
这让我有点难过,至于如何使test.so调用由被调用者定义的东西。你能帮忙吗?
答案 0 :(得分:1)
这里至少有三个不同的问题:
较小的一个是您有两个名为main.cpp
的文件,并且不完全清楚哪个命令引用了您问题中的哪个文件。
更大的问题是,您希望{。1}}绑定到a.out中的test.so
,但该函数不是来自{{1}的导出 } 除非参与链接的某个共享库引用该函数,或与registerfunc
链接(导出所有函数)。这是真正的解决方案。
您可以使用以下命令查看从a.out
导出的功能:
-Wl,--export-dynamic
最后,当你这样做时:
a.out
您实际上是在创建一个共享库(名为nm -D a.out | grep ' T '
),而不是可执行文件。像运行可执行文件一样运行这样的共享库会导致您观察到的崩溃。