C++ 库未正确导出函数

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

我有一个用于Windows和Linux的共享库(.dll和.so)。除了用于平台之间差异的一些定义外,代码完全相同。Windows DLL工作正常,所有符号都已导出,调用方可以使用

但是在Linux下有一个问题,当尝试调用其中一个函数时,调用应用程序会以“symbol not found”消息终止。令人惊讶的是,当我查看.so文件(使用Midnight Commander)时,我可以看到相关的符号在那里,因此在我看来,没有理由失败

这是一个库定义的示例

标题:

#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)