C++ 库未正确导出函数
我有一个用于Windows和Linux的共享库(.dll和.so)。除了用于平台之间差异的一些定义外,代码完全相同。Windows DLL工作正常,所有符号都已导出,调用方可以使用 但是在Linux下有一个问题,当尝试调用其中一个函数时,调用应用程序会以“symbol not found”消息终止。令人惊讶的是,当我查看.so文件(使用Midnight Commander)时,我可以看到相关的符号在那里,因此在我看来,没有理由失败 这是一个库定义的示例 标题:C++ 库未正确导出函数,c++,c,linux,shared-libraries,libtool,C++,C,Linux,Shared Libraries,Libtool,我有一个用于Windows和Linux的共享库(.dll和.so)。除了用于平台之间差异的一些定义外,代码完全相同。Windows DLL工作正常,所有符号都已导出,调用方可以使用 但是在Linux下有一个问题,当尝试调用其中一个函数时,调用应用程序会以“symbol not found”消息终止。令人惊讶的是,当我查看.so文件(使用Midnight Commander)时,我可以看到相关的符号在那里,因此在我看来,没有理由失败 这是一个库定义的示例 标题: #ifdef ENV_LINUX
#ifdef ENV_LINUX
#ifdef MY_EXPORTS
#define MY_API __attribute ((visibility ("default")))
#else
#define MY_API
#endif
#else
#ifdef MY_EXPORTS
#define MY_API __declspec(dllexport)
#else
#define MY_API __declspec(dllimport)
#endif
#endif
#ifdef __cplusplus
extern "C"
{
#endif
MY_API unsigned char MY_set_connection(const char *address);
#ifdef __cplusplus
};
#endif // __cplusplus
以及实施:
MY_API unsigned char MY_set_connection(const char *address)
{
// some code here
}
因此,header和C-file中的函数定义是相同的,库是用
CCOMPILER=libtool --mode=compile g++ -Wall -Wno-unused -fPIC -shared -fvisibility=hidden $(DBGFLAGS) -DMY_EXPORTS -D_REENTRANT -DENV_LINUX -I. -I.. $(CFLAGS) $(LFLAGS)
LINK=libtool --mode=link g++ -rpath /usr/lib
所以在我看来,没有理由在运行时找不到符号。你知道原因是什么吗?你的链接出了问题。符号是在编译时找到的,但不是在运行时?您是否使用
dl\u open
运行时链接库
我把这个简单的例子放在一起调试
#include <iostream>
#ifdef ENV_LINUX
#ifdef MY_EXPORTS
#define MY_API __attribute ((visibility ("default")))
#else
#define MY_API
#endif
#else
#ifdef MY_EXPORTS
#define MY_API __declspec(dllexport)
#else
#define MY_API __declspec(dllimport)
#endif
#endif
#ifdef __cplusplus
extern "C"
{
#endif
MY_API unsigned char MY_set_connection(const char *address);
#ifdef __cplusplus
};
#endif // __cplusplus
unsigned char MY_set_connection(const char* address)
{
std::cout << "found it" << std::endl;
return 0;
}
现在是一个简单的主
#ifdef __cplusplus
extern "C"
{
#endif
unsigned char MY_set_connection(const char *address);
#ifdef __cplusplus
};
#endif // __cplusplus
int main(int argc, char* argv[])
{
unsigned char rc = MY_set_connection("test");
return 0;
}
编译并检查符号依赖关系
/tmp$ g++ -g -std=c++11 junk.cpp -DENV_LINUX -L . -l test_library
/tmp$ g++ -g junk.cpp -DENV_LINUX -L . -l test_library
/tmp$ nm a.out | grep MY_
U MY_set_connection
所以我的集合连接是'U',这是未定义的,正如预期的那样。符号为“T”,也应为文本部分和外部符号。运行该程序可以按预期工作。请查看您与nm的符号依赖关系,可能是符号状态错误
另一种可能是外部C签名在库或主库中错误。确保符号在两个nm输出中均未损坏
查看ldd输出,确保在运行时链接到正确的库。针对错误版本的共享库的运行时链接将给出未定义的符号
ldd ./a.out
libtest_library.so => /tmp/libtest_library.so (0x00002b5df4ca7000)
你的活动没有装饰吗?是什么给了你
readelf-Ws yourlib.so
,还是nm-D yourlib.so
nm返回“0000000000003f80 T MY_set_connection”,那么函数应该正常?加载是通过dl_open动态完成的。是的,这对于库来说是正确的。在可执行文件上也执行nm。还可以使用ldd确保获得正确版本的库
ldd ./a.out
libtest_library.so => /tmp/libtest_library.so (0x00002b5df4ca7000)