【问题标题】:Call C++ functions containing STL data types from C从 C 调用包含 STL 数据类型的 C++ 函数
【发布时间】:2017-05-12 08:47:00
【问题描述】:

我在 C++ 中有一个函数,它使用来自 STL 的 vectormap 等数据类型。下面是一些示例代码:

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

ma​​in.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?

Elegantly call C++ from C

http://www.cplusplus.com/forum/general/8997/

但找不到我的问题的解决方案。

【问题讨论】:

  • 为什么 c 编译器会知道如何编译 c++ 组件。也许您需要完全编译 c++ 组件,然后链接二进制文件。
  • 这个问题看起来像是你链接到的那些人的欺骗。答案描述了一般可能的解决方案,您需要在具体代码中实现它们,仅此而已。
  • 使用g++链接代码(不是gcc——该程序是一个C++程序,因为它包含一些C++)。通常最好使用g++ 来编译包含main() 的文件,因为它在C++ 中具有特殊属性(与C 中不同),尽管您可以使用C 编译器来创建包含main() 的目标文件。
  • 您可以尝试使用gccmain.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++ -vgcc -v 执行不同的链接操作,并查看执行链接时调用的命令有多大差异。

标签: c++ c gcc


【解决方案1】:

用C编译器自己编译C文件:

gcc -c cfile.c

然后用 C++ 编译器链接所有文件:

g++ -o a.out main.o cfile.o mylib.o

请注意,您必须使用 C++ 编译器使用 main 函数编译文件。任何其他文件都可以使用其中任何一个编译,但您需要 extern "C" 声明才能从 C++ 调用 C 代码或创建可以从 C 调用的 C++ 函数

【讨论】:

    【解决方案2】:

    我已经在 g++ 中构建了所有文件,但没有出现链接错误。你能把所有的源文件编译成 gcc 或 g++。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-10-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-04-12
      • 1970-01-01
      • 2013-04-11
      相关资源
      最近更新 更多