0

我正在使用以下说明构建一个共享库:

cc -shared -Wl,-soname,libmy.so.0 [lots of .o files] -o libmy.so.0
ln -f -s libmy.so.0 libmy.so

我不知道这是否重要,但这个库是用 C 编写的。

然后我尝试从 C++ 程序链接到这个库:

/usr/bin/c++ -g CMakeFiles/codegen.dir/client/codegen.cpp.o CMakeFiles/codegen.dir
 /namenode/shared_objects.cpp.o  -o codegen -rdynamic -L/path/to/libmy -lpthread
 -lboost_system-mt -lboost_filesystem-mt -lboost_unit_test_framework-mt
 -lboost_serialization-mt -lmy -Wl,-rpath,/path/to/libmy

但是ld报错:

CMakeFiles/codegen.dir/client/codegen.cpp.o: In function `main':
[...]/src/client/codegen.cpp:46:
   undefined reference to `alloc_code(int, int, int, int, int)'

即使alloc_code似乎在共享库中:

$ nm libmy.so | grep alloc_code
0000000000002c80 T alloc_code

请注意,libmy.so我的codegen程序是使用不同的编译器标志编译的(一个在调试模式下编译,而另一个在优化模式下编译),但我认为问题不是来自这里。

是什么导致ld无法链接?codegenlibmy.so

4

1 回答 1

1

您的 C 函数需要声明为 C++,如下所示:

#ifdef __cplusplus
extern "C" {
#endif

void alloc_code(int, int, int, int, int);

#ifdef __cplusplus
}
#endif

否则,编译器和链接器假定 C++ 链接(其中可以存在多个具有相同名称的函数,只要它们的参数不同) - 并且将搜索函数的“C++-mangled”变体。

使用时,extern "C"您告诉编译器和链接器使用未损坏的“C”名称。

为了演示这一点,让我们编写相同的“库”并同时使用 C 编译器和 C++ 编译器对其进行编译:

/* Library Source Code */
int library_function(void) {
    return 0;
}

然后用C编译:

gcc -o libdummy.so -shared -fPIC dummy-library.c
nm libdummy.so | grep library_function

哪个输出:

0000000000000640 T library_function

用 C++ 编译器运行同样的东西会产生:

g++ -o libdummy.so -shared -fPIC dummy-library.c
nm libdummy.so

=>

0000000000000670 T _Z16library_functionv
于 2013-10-01T16:46:05.383 回答