【问题标题】:How can I link C++ files to a C program?如何将 C++ 文件链接到 C 程序?
【发布时间】:2013-05-25 04:18:57
【问题描述】:

我目前正在尝试将大型 C++ 程序链接到 C“包装器”,以允许与编译器理解 C 但不理解 C++(准确地说是 Haskell GHC)的另一种语言的程序集成。这样做,无论是使用 GHC 还是 GCC,都会遇到奇怪的问题。

为了简明扼要地模拟这种情况,假设我在 C 中有一个主程序文件:

cmain.c

#include "header.h"
#include <stdio.h>

int main () {
  printf("%d\n", cppfun(12));

  return 0;
}

以及在 .cpp 文件中定义的辅助函数:

cppmodule.cpp

#include "header.h"
#include "further.h"

class foobar {
public:
  int getfive () {return 5;}
};

extern "C" { 
int cppfun(int foo) {
  foobar fb;

  return fb.getfive();
}
}

这么多可以编译得很好。但是,如果 cppmodule.cpp 引用另一个 .cpp 文件,如下所示:

cppmodule.cpp mk II

#include "header.h"
#include "further.h"

class foobar {
public:
  int getfive () {return 5;}
};

extern "C" { 
int cppfun(int foo) {
  foobar fb;

  return fb.getfive() + morecpp();
}
}

新的 .cpp 文件在哪里类似;

morecpp.cpp

#include "further.h"

class moreobjects {
public:
  int getsix() {return 6;}
};


#ifdef __cplusplus
extern "C" {
#endif


int morecpp() {
  moreobjects mo;

  return mo.getsix();
}

#ifdef __cplusplus
}
#endif

当我尝试使用“gcc cmain.o cppmodule.o morecpp.o”之类的命令进行编译时,突然出现错误;使用 g++ 编译是可行的,但正如我所提到的,这种解决方案不符合我的目的。

我在编译这个例子时遇到的错误是

max@SoutheastCorner:~/Projectsync/maketest$ gcc cmain.o cppmodule.o morecpp.o
cppmodule.o:(.eh_frame+0x4b): undefined reference to `__gxx_personality_v0'
collect2: error: ld returned 1 exit status

与我的实际项目代码相同的尝试还给出了格式错误的屏幕截图

hopnode.cpp:(.text._ZN9__gnu_cxx13new_allocatorISt10_List_nodeI4nodeIPcS3_EEE8allocateEmPKv[_ZN9__gnu_cxx13new_allocatorISt10_List_nodeI4nodeIPcS3_EEE8allocateEmPKv]+0x4d): undefined reference to `operator new(unsigned long)'
/tmp/ccaoEEFM.o: In function `__gnu_cxx::new_allocator<std::_Rb_tree_node<std::pair<char* const, node<char*, char*> > > >::allocate(unsigned long, void const*)':
hopnode.cpp:(.text._ZN9__gnu_cxx13new_allocatorISt13_Rb_tree_nodeISt4pairIKPc4nodeIS3_S3_EEEE8allocateEmPKv[_ZN9__gnu_cxx13new_allocatorISt13_Rb_tree_nodeISt4pairIKPc4nodeIS3_S3_EEEE8allocateEmPKv]+0x2c): undefined reference to `std::__throw_bad_alloc()'
hopnode.cpp:(.text._ZN9__gnu_cxx13new_allocatorISt13_Rb_tree_nodeISt4pairIKPc4nodeIS3_S3_EEEE8allocateEmPKv[_ZN9__gnu_cxx13new_allocatorISt13_Rb_tree_nodeISt4pairIKPc4nodeIS3_S3_EEEE8allocateEmPKv]+0x46): undefined reference to `operator new(unsigned long)'

任何见解都将不胜感激。

【问题讨论】:

  • 我看过那个问题,但如果我的问题的答案包含在我无法理解的内容中。
  • 有很多重复的,但也许我没有选择最好的。无论如何,解决方案在我链接的问题的第一个答案中;要么与 G++ 链接,要么添加-lstdc++

标签: c++ c gcc compiler-construction g++


【解决方案1】:

问题出在链接阶段。您的程序缺少 C++ 标准库中的符号。要解决此问题,您必须链接 g++ 驱动程序,或者必须显式链接 C++ 标准库。

使用 g++ 链接是最简单的解决方案,但您也可以尝试添加 -lstdc++ 作为库标志。

请记住,与此相关的陷阱仍然很多。 C++ ABI 并不简单,并且在编译器(clang/g++/等)甚至不同版本的 GCC 之间不一定一致。如果您的 Haskell 程序动态链接到使用不同 C++ ABI 编译的其他 C++ 代码,这可能是一个问题。

还请注意,您还必须在 C/C++ 边界捕获所有异常。 Haskell 需要一个直接的 C ABI,并且无法处理通过 C/C++ 边界泄漏的 C++ 异常。

【讨论】:

  • 我尝试用 g++ 链接,得到了相同的结果。但是将 -lstdc++ 赋予 GHC 是可行的,这是我没有想到的。谢谢!
【解决方案2】:

如果您想在 C 代码中包含 C++ 代码,请在 C 程序使用的所有 C++ 代码周围使用extern "C++"。然后你可以将它编译为 C 程序,Haskell 甚至不会知道它是在幕后使用一些 C++ 代码实现的。

编辑:我从未尝试过这个方向(通常你在 C++ 项目中使用 C 代码),但基本上它应该是这样工作的。

如果它不能正常工作,请尝试像使用 g++ 的任何普通 C++ 程序一样编译 C++ 程序,然后编写一个使用它的 C 程序。

【讨论】:

    【解决方案3】:

    我会尝试将 extern "C" 添加到将在 C 中调用的 c++ 函数中。C++ 编译器必须知道该函数将由 C 编译器使用 extern "C" 构造调用。

    // 在你的 C++ 代码中

    // 使用 extern "C" 将 function(char, int) 声明为 c 函数: extern "C" void 函数(char c, int i);

    ...

    // 在 C++ 模块中实现函数(char,int): 无效函数(char c,int i) { ... }

    【讨论】:

      猜你喜欢
      • 2017-07-10
      • 2019-04-11
      • 2013-08-26
      • 2023-01-26
      • 1970-01-01
      • 2011-02-06
      • 2014-09-08
      • 1970-01-01
      • 2016-07-06
      相关资源
      最近更新 更多