如何将c++文件链接到C程序

How can I link C++ files to a C program?

本文关键字:程序 链接 文件 c++      更新时间:2023-10-16

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

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

cmain.c

#include "header.h"
#include <stdio.h>
int main () {
  printf("%dn", 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)'

问题出在链接阶段。您的程序缺少c++标准库中的符号。要解决这个问题,你必须要么链接到c++驱动程序,要么明确地链接到c++标准库。

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

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

还要注意,还必须捕获C/c++边界的所有异常。Haskell期望一个直接的C ABI,不能处理通过C/c++边界泄漏的c++异常。

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

编辑:我从来没有尝试过这个方向(通常你在c++项目中使用C代码),但基本上这就是它应该如何工作。

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

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

//在你的c++代码中

//使用extern " c "声明function(char, int)为c函数:

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