如何从 POSIX 共享库导出符号并使用 dlopen、dlsym 加载
How to export symbols from POSIX shared library and load using dlopen, dlsym
我们正在使用 dlopen 读取 Mac OS X 上的动态库。更新:
这是一个posix问题,同样的事情在cygwin下失败了。
首先编译。在 cygwin 上:
extern "C" void foo() { }
g++ -shared foo.c -o libfoo.so
nm -D libfoo.so
不显示 public 符号。这似乎是问题所在。如果我可以使它们 public,nm -D 应该显示它们。
使用:
nm libfoo.so | grep foo
000000x0xx0x00x0x0 T _foo
你可以看到符号在那里。在 Linux 中,这似乎有效:
nm -D foo.so
0000000000201020 B __bss_start
w __cxa_finalize
0000000000201020 D _edata
0000000000201028 B _end
0000000000000608 T _fini
0000000000000600 T foo
w __gmon_start__
00000000000004c0 T _init
w _ITM_deregisterTMCloneTable
w _ITM_registerTMCloneTable
w _Jv_RegisterClasses
然而,即使在 Linux 中,我们似乎也无法连接到图书馆。这是源代码:
包括
包括
使用命名空间标准;
int main() {
void* so = dlopen("foo.so", RTLD_NOW);
if (so = nullptr) {
cerr << "Can't open shared library\n";
exit(-1);
}
#if 0
const void* sym = dlsym(so, "foo");
if (sym == nullptr) {
cout << "Symbol not found\n";
}
#endif
dlclose(so);
}
如果我们删除#ifdef,上面的代码会打印"Symbol not found"
但它在 dlclose 上崩溃了。
我们尝试导出 LD_LIBRARY_PATH=。只是为了看看是否无法到达图书馆。而且 dlopen 调用似乎在任何情况下都有效,return 不是 nullptr。
总而言之,该库似乎不适用于 Mac 和 Cygwin。 Linux nm -D 显示库中的符号,但加载符号的代码不起作用。
在您的示例中,您编写了 if (so = nullptr) {
,它将 nullptr
分配给 so
,并且条件始终为假。 -Wall
是调试时的好主意!
这本身就解释了为什么你不能加载符号,但我还发现我需要做 dlopen("./foo.so", RTLD_NOW);
因为 dlopen
否则搜索库路径,而不是当前目录。
我们正在使用 dlopen 读取 Mac OS X 上的动态库。更新: 这是一个posix问题,同样的事情在cygwin下失败了。
首先编译。在 cygwin 上:
extern "C" void foo() { }
g++ -shared foo.c -o libfoo.so
nm -D libfoo.so
不显示 public 符号。这似乎是问题所在。如果我可以使它们 public,nm -D 应该显示它们。
使用:
nm libfoo.so | grep foo
000000x0xx0x00x0x0 T _foo
你可以看到符号在那里。在 Linux 中,这似乎有效:
nm -D foo.so
0000000000201020 B __bss_start
w __cxa_finalize
0000000000201020 D _edata
0000000000201028 B _end
0000000000000608 T _fini
0000000000000600 T foo
w __gmon_start__
00000000000004c0 T _init
w _ITM_deregisterTMCloneTable
w _ITM_registerTMCloneTable
w _Jv_RegisterClasses
然而,即使在 Linux 中,我们似乎也无法连接到图书馆。这是源代码:
包括
包括
使用命名空间标准;
int main() {
void* so = dlopen("foo.so", RTLD_NOW);
if (so = nullptr) {
cerr << "Can't open shared library\n";
exit(-1);
}
#if 0
const void* sym = dlsym(so, "foo");
if (sym == nullptr) {
cout << "Symbol not found\n";
}
#endif
dlclose(so);
}
如果我们删除#ifdef,上面的代码会打印"Symbol not found" 但它在 dlclose 上崩溃了。
我们尝试导出 LD_LIBRARY_PATH=。只是为了看看是否无法到达图书馆。而且 dlopen 调用似乎在任何情况下都有效,return 不是 nullptr。
总而言之,该库似乎不适用于 Mac 和 Cygwin。 Linux nm -D 显示库中的符号,但加载符号的代码不起作用。
在您的示例中,您编写了 if (so = nullptr) {
,它将 nullptr
分配给 so
,并且条件始终为假。 -Wall
是调试时的好主意!
这本身就解释了为什么你不能加载符号,但我还发现我需要做 dlopen("./foo.so", RTLD_NOW);
因为 dlopen
否则搜索库路径,而不是当前目录。