【问题标题】:Can't link a C shared object to a C++ program无法将 C 共享对象链接到 C++ 程序
【发布时间】:2018-04-14 21:49:27
【问题描述】:

我正在尝试为一个项目编写一个 makefile。该项目涉及一个测试程序,它定义了一个用 C++11 编写的 main 函数,该函数应该调用一个用 c99 编写的共享对象库并运行一些测试。

我的 makefile 成功编译 c99 库并生成“libhanoi.so”。

当我尝试将 C99 库链接到 C++11 部分时,我收到以下错误:

g++ -std=gnu++11 -L. -lhanoi -o main tests/testing.cpp tests/main.cpp
/tmp/cctHQTcW.o: In function `binarion_constructor(unsigned long*)':
main.cpp:(.text+0x28): undefined reference to `binarion64_t'
collect2: error: ld returned 1 exit status
Makefile:29: recipe for target 'tests' failed
make: *** [tests] Error 1

但是,“nm -C libhanoi.so”的输出显示 binarion64_t 函数正在由 libhanoi.so 导出:

0000000000000610 T binarion64_t(long long, long long)

当我在 libhanoi.so 的名称中引入一个错字时,它会引入一个错误,说它找不到 libhanoi.so。

所以它必须能够找到 libhanoi.so 并且 libhanoi.so 正在导出 main.cpp 中未实现的函数,但它仍然给出未定义的引用。怎么回事?

小例子:

hanoi.h:

#ifndef HANOI_H
#define HANOI_H

#include <inttypes.h>

// binarion (base -1+i) constructor
uint64_t binarion64_t(long long A, long long B);


#endif // HANOI_H

binarion.c:

#include "hanoi.h"

uint64_t binarion64_t(long long A,long long B){
    return 0;
}

main.cpp:

#include <stdio.h>

extern "C" {
#include "hanoi.h"
};

uint64_t binarion_constructor(uint64_t * args){
   return binarion64_t(args[0], args[1]);
}

int main(void){
   return 0;
}

编译:

g++ -std=c99 -c binarion.c
g++ -std=c99 -shared -o libhanoi.so binarion.o -lm
g++ -std=gnu++11 -L. -lhanoi -o main main.cpp

输出:

/tmp/ccjoRmCg.o: In function `binarion_constructor(unsigned long*)':
main.cpp:(.text+0x28): undefined reference to `binarion64_t'
collect2: error: ld returned 1 exit status

编辑:

我正在运行的命令是:

gcc -std=c99 -c binarion.c
gcc -std=c99 -shared -o libhanoi.so binarion.o -lm
g++ -std=gnu++11 -L. -lhanoi -o main main.cpp

文件正是问题中的文件。 “readelf -s libhanoi.so | grep binarion”的输出是:

12: 0000000000000660    19 FUNC    GLOBAL DEFAULT   11 binarion64_t
33: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS binarion.c
46: 0000000000000660    19 FUNC    GLOBAL DEFAULT   11 binarion64_t

“g++ -std=gnu++11 -L.-lhanoi -o main main.cpp”的输出为:

/tmp/cczfgY8M.o: In function `binarion_constructor(unsigned long*)':
main.cpp:(.text+0x28): undefined reference to `binarion64_t'
collect2: error: ld returned 1 exit status

【问题讨论】:

  • 在 C++ 代码中包含 C 标头时,您必须将包含内容包装到 extern "C" { } 中。否则函数名称会被破坏。最好把#ifdef __cplusplus\nextern "C" {\n#endif放在标题的开头,#ifdef __cplusplus\n}\n#endif放在底部。
  • 我尝试在 extern "C" { } 括号内外包含定义 binarion64_t 的标头和函数声明本身,但没有成功。
  • 嗯。然后请提供minimal reproducible example
  • 我无法重现该问题;我的尝试正如我希望/期望的那样奏效。 HolyBlackCat 的建议很好。
  • 按要求添加了一个最小示例。

标签: c++ compiler-errors linker


【解决方案1】:

TL;博士:

用途:

gcc -std=c99 -c binarion.c
gcc -std=c99 -shared -o libhanoi.so binarion.o -lm
g++ -std=gnu++11 -L. -lhanoi -o main main.cpp

解释:

您应该使用gcc 编译C 文件,g++ 用于C++。当您执行g++ -std=c99 -c binarion.c 时,编译器会提示您:

cc1plus: warning: command line option ‘-std=c99’ is valid for C/ObjC but not for C++

这意味着您最终会将您的库编译为 C++ 库。你可以通过调用readelf -s libhanoi.so | grep binarion来验证:

 9: 00000000000005da    19 FUNC    GLOBAL DEFAULT    9 _Z12binarion64_txx
29: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS binarion.c
44: 00000000000005da    19 FUNC    GLOBAL DEFAULT    9 _Z12binarion64_txx

如您所见,该函数已被命名,这是 C++ 所做的,而 C 没有。

但是,在编译 main.cpp 时,您会告诉编译器 binarion_t 具有 C 链接:

extern "C" {
#include "hanoi.h"
};

所以它正在搜索未损坏的binarion_t(而不是_Z12binarion64_txx)。

【讨论】:

  • 此解决方案无法完全发挥作用。运行这些命令后“readelf -s libhanoi.so | grep binarion”的输出显示未损坏的名称,但我仍然得到相同的未定义引用错误。 (这是问题中的确切设置。)
  • @firstnamegklsodascb 那么您要么编译的文件与此处发布的文件不同,要么编译器有问题。您能否使用您使用的确切文件、编译它们的确切命令以及readelf -s libhanoi.so | grep binarion 的输出来更新您的问题?
猜你喜欢
  • 2014-09-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多