我正在尝试将一个大的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)'
非常感谢任何见解。
答案 0 :(得分:2)
问题出在链接阶段。您的程序缺少C ++标准库中的符号。要解决此问题,您必须链接到g ++驱动程序,或者必须在C ++标准库中显式链接。
与g ++链接是最简单的解决方案,但您也可以尝试添加-lstdc++
作为库标记。
请记住,仍有很多与此相关的陷阱。 C ++ ABI并不简单,并且不一定在编译器(clang / g ++ /等)或甚至不同版本的GCC之间保持一致。如果您的Haskell程序动态链接到使用不同C ++ ABI编译的其他C ++代码,则可能会出现问题。
另请注意,您还必须捕获C / C ++边界的所有异常。 Haskell期望直接的C ABI并且不能处理通过C / C ++边界泄漏的C ++异常。
答案 1 :(得分:0)
如果您想在C代码中使用C ++代码,请在C程序使用的所有C ++代码周围使用extern "C++"
。然后你可以将它编译为C程序,而Haskell甚至不知道它是在幕后使用一些C ++代码实现的。
如果它不起作用,尝试像使用g ++的普通C ++程序一样编译C ++程序,然后编写一个使用它的C程序。
答案 2 :(得分:0)
我会尝试将extern“C”添加到将在C中调用的c ++函数.C ++编译器必须知道该函数将由C编译器使用extern“C”构造调用。
//在您的C ++代码中
//使用extern“C”将函数(char,int)声明为c函数: extern“C”void函数(char c,int i);
...
//在C ++模块中实现函数(char,int): void函数(char c,int i) { ... }