【发布时间】:2017-05-12 08:47:00
【问题描述】:
我在 C++ 中有一个函数,它使用来自 STL 的 vector 和 map 等数据类型。下面是一些示例代码:
mylib.cpp
#include "mylib.h"
#include<vector>
using namespace std;
int summation(int n) {
vector<int> numbers;
int sum = 0;
for(int i = 1; i <=n; i++)
numbers.push_back(i);
for(int j = 0; j < numbers.size(); j++)
sum += numbers[j];
return sum;
}
我创建了一个头文件如下:
mylib.h
#ifdef _cplusplus
extern "C" {
#endif
extern int summation(int n);
#ifdef _cplusplus
};
#endif
使用命令将C++文件编译成对象代码
g++ -o mylib.o -c mylib.cpp
然后,我编写了一个 C 程序,以便使用其中的函数 summation。
main.c
#include<stdio.h>
#include "mylib.h"
int main() {
int n;
scanf("%d", &n);
printf("%d", summation(n));
return 0;
}
现在,当我使用 gcc 编译上面的 C 文件时,
gcc main.c mylib.o
我收到以下错误
/tmp/ccAMN2ld.o: In function `main':
main.c:(.text+0x33): undefined reference to `summation'
mylib.o: In function `std::vector<int, std::allocator<int> >::_M_insert_aux(__gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int> > >, int const&)':
mylib.cpp:(.text._ZNSt6vectorIiSaIiEE13_M_insert_auxEN9__gnu_cxx17__normal_iteratorIPiS1_EERKi[_ZNSt6vectorIiSaIiEE13_M_insert_auxEN9__gnu_cxx17__normal_iteratorIPiS1_EERKi]+0x26e): undefined reference to `__cxa_begin_catch'
mylib.cpp:(.text._ZNSt6vectorIiSaIiEE13_M_insert_auxEN9__gnu_cxx17__normal_iteratorIPiS1_EERKi[_ZNSt6vectorIiSaIiEE13_M_insert_auxEN9__gnu_cxx17__normal_iteratorIPiS1_EERKi]+0x2d7): undefined reference to `__cxa_rethrow'
mylib.cpp:(.text._ZNSt6vectorIiSaIiEE13_M_insert_auxEN9__gnu_cxx17__normal_iteratorIPiS1_EERKi[_ZNSt6vectorIiSaIiEE13_M_insert_auxEN9__gnu_cxx17__normal_iteratorIPiS1_EERKi]+0x2df): undefined reference to `__cxa_end_catch'
mylib.o: In function `std::vector<int, std::allocator<int> >::_M_check_len(unsigned long, char const*) const':
mylib.cpp:(.text._ZNKSt6vectorIiSaIiEE12_M_check_lenEmPKc[_ZNKSt6vectorIiSaIiEE12_M_check_lenEmPKc]+0x5b): undefined reference to `std::__throw_length_error(char const*)'
mylib.o: In function `__gnu_cxx::new_allocator<int>::deallocate(int*, unsigned long)':
mylib.cpp:(.text._ZN9__gnu_cxx13new_allocatorIiE10deallocateEPim[_ZN9__gnu_cxx13new_allocatorIiE10deallocateEPim]+0x1c): undefined reference to `operator delete(void*)'
mylib.o: In function `__gnu_cxx::new_allocator<int>::allocate(unsigned long, void const*)':
mylib.cpp:(.text._ZN9__gnu_cxx13new_allocatorIiE8allocateEmPKv[_ZN9__gnu_cxx13new_allocatorIiE8allocateEmPKv]+0x2c): undefined reference to `std::__throw_bad_alloc()'
mylib.cpp:(.text._ZN9__gnu_cxx13new_allocatorIiE8allocateEmPKv[_ZN9__gnu_cxx13new_allocatorIiE8allocateEmPKv]+0x3c): undefined reference to `operator new(unsigned long)'
mylib.o:(.eh_frame+0x4b): undefined reference to `__gxx_personality_v0'
collect2: error: ld returned 1 exit status
我必须使用 gcc 来编译 C 文件。有没有办法让它工作?
我尝试寻找解决方案并偶然发现了以下链接,
How to call C++ function from C?
http://www.cplusplus.com/forum/general/8997/
但找不到我的问题的解决方案。
【问题讨论】:
-
为什么 c 编译器会知道如何编译 c++ 组件。也许您需要完全编译 c++ 组件,然后链接二进制文件。
-
这个问题看起来像是你链接到的那些人的欺骗。答案描述了一般可能的解决方案,您需要在具体代码中实现它们,仅此而已。
-
使用
g++链接代码(不是gcc——该程序是一个C++程序,因为它包含一些C++)。通常最好使用g++来编译包含main()的文件,因为它在C++ 中具有特殊属性(与C 中不同),尽管您可以使用C 编译器来创建包含main()的目标文件。 -
您可以尝试使用
gcc将main.c编译为main.o,然后与g++ -o program main.o mylib.o链接——您可能会很幸运并且侥幸逃脱。否则,创建包含extern "C" int c_main(); int main() { return c_main(); }(或extern "C" int c_main(int argc, char **argv); int main(int argc, char **argv) { return c_main(argc, argv); })的cpp-main.cpp并使用g++编译它。在现有的main.c中,将函数更改为int c_main(void) { …your code… }(或带参数的等效项),不要忘记声明函数(因为它不再称为main())。 -
关键点是将程序与
g++链接,以便您获得正确的C++ 库链接。相比之下,与gcc链接将是一个痛苦的练习。如有疑问,请尝试使用g++ -v和gcc -v执行不同的链接操作,并查看执行链接时调用的命令有多大差异。