简体   繁体   English

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

[英]How can I link C++ files to a C program?

I'm currently trying to link a big C++ program to a C "wrapper," to allow integration with a program in another language whose compiler understands C but not C++ (Haskell GHC, to be precise.) But my attempts to do so, either with GHC or GCC, meet strange problems. 我目前正在尝试将一个大的C ++程序链接到一个C“包装器”,以允许与另一种语言的程序集成,该程序编译器理解C而不是C ++(确切地说是Haskell GHC)。但是我试图这样做,无论是GHC还是GCC,遇到奇怪的问题。

To model the situation concisely, say I have a main program file in C: 为了简明地描述情况,假设我在C中有一个主程序文件:

cmain.c cmain.c

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

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

  return 0;
}

and a helper function defined in a .cpp file: 和.cpp文件中定义的辅助函数:

cppmodule.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();
}
}

This much will compile just fine. 这将编译得很好。 But if, instead, cppmodule.cpp refers to a further .cpp file, like so: 但是,如果相反,cppmodule.cpp引用了另一个.cpp文件,如下所示:

cppmodule.cpp mk II 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();
}
}

where the new .cpp file is something similar; 新的.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

I suddenly get an error when I'm trying to compile with a command like "gcc cmain.o cppmodule.o morecpp.o"; 当我尝试使用像“gcc cmain.o cppmodule.o morecpp.o”这样的命令编译时,我突然收到错误; compiling with g++ works but, as I mentioned, this kind of solution doesn't fit my purposes. 用g ++编译工作,但正如我所提到的,这种解决方案不符合我的目的。

The error I get trying to compile this example is 我试图编译这个例子的错误是

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

The same kind of attempt with my actual project code additionally gives screenfulls of errors of the form 与我的实际项目代码相同的尝试另外给出了窗体的错误

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)'

Any insights would be greatly appreciated. 任何见解将不胜感激。

The problem is at the link stage. 问题出在链接阶段。 Your program is missing the symbols from the C++ standard library. 您的程序缺少C ++标准库中的符号。 To fix this, you have to either link with the g++ driver or you have to explicitly link in the C++ standard library. 要解决此问题,您必须链接到g ++驱动程序,或者必须在C ++标准库中显式链接。

Linking with g++ is the easiest solution, but you can also try adding -lstdc++ as a library flag. 与g ++链接是最简单的解决方案,但您也可以尝试添加-lstdc++作为库标志。

Keep in mind that there are still a lot of pitfalls associated with this. 请记住,仍有很多与此相关的陷阱。 The C++ ABI is not simple, and is not necessarily consistent across compilers (clang/g++/etc.) or even different versions of GCC. C ++ ABI并不简单,并且不一定在编译器(clang / g ++ /等)或甚至不同版本的GCC之间保持一致。 This can be a problem if your Haskell program dynamically links to other C++ code compiled with a different C++ ABI. 如果您的Haskell程序动态链接到使用不同C ++ ABI编译的其他C ++代码,则可能会出现问题。

Also note that you also must catch all exceptions at the C/C++ boundary. 另请注意,您还必须捕获C / C ++边界的所有异常。 Haskell expects a straight C ABI and cannot deal with C++ exceptions that leak through the C/C++ boundary. Haskell期望直接的C ABI并且不能处理通过C / C ++边界泄漏的C ++异常。

If you want to have C++ code in C code, use extern "C++" around all the C++ code which your C program uses. 如果你想在C代码中使用C ++代码,请在C程序使用的所有C ++代码周围使用extern "C++" Then you can compile it as a C program and Haskell wouldn't even know that it's implemented using some C++ code behind the scenes. 然后你可以将它编译为C程序,Haskell甚至不知道它是在幕后使用一些C ++代码实现的。

EDIT: I never tried this direction (usually you use C code in a C++ project), but basically this is how it's supposed to work. 编辑:我从来没有尝试过这个方向(通常你在C ++项目中使用C代码),但基本上这就是它应该如何工作。

If it doesn't just work, try compiling the C++ program like any normal C++ program with g++, then write a C program which uses it. 如果它不起作用,尝试像使用g ++的任何普通C ++程序一样编译C ++程序,然后编写一个使用它的C程序。

I would try adding extern "C" to c++ functions that will be called in C. The C++ compiler must know that the function is to be called by a C compiler using the extern "C" construct. 我会尝试将extern“C”添加到将在C中调用的c ++函数.C ++编译器必须知道该函数将由C编译器使用extern“C”构造调用。

// In your C++ code //在您的C ++代码中

// Declare function(char, int) as ac function using extern "C": extern "C" void function(char c, int i); //使用extern“C”将函数(char,int)声明为ac函数:extern“C”void函数(char c,int i);

... ...

// Implement function(char,int) in C++ module: void function(char c, int i) { ... } //在C ++模块中实现函数(char,int):void function(char c,int i){...}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM