2013-05-29 25 views
3

我正在嘗試將一個大的C++程序鏈接到一個C「包裝器」,以允許與另一種編譯器理解C而不是C++(Haskell GHC,準確地說)的語言進行集成。但是我嘗試去做所以,無論是與GHC或GCC,遇到奇怪的問題。如何將C++文件鏈接到C程序?

的情況簡潔的模型,說我有在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 ++編譯工作,但正如我所提到的,這種解決方案不適合我的目的。

錯誤我在嘗試編譯這個例子是

[email protected]:~/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)' 

任何見解將是錯誤的screenfulls不勝感激。

+1

的可能重複的[什麼是的\ _ \ _ gxx \ _personality \ _v0 for?](http://stackoverflow.com/questions/329059/what-is-gxx-personality-v0-for) –

+0

我看過這個問題,但如果一個答案我的問題包含在我未能理解的範圍內。 – Maxander

+2

有很多重複,但也許我沒有選擇最好的一個。無論如何,解決方案是在我所鏈接的問題的第一個答案;要麼與G ++鏈接,要麼添加'-lstdC++'。 –

回答

2

問題出在鏈接階段。您的程序缺少來自C++標準庫的符號。要解決這個問題,您必須鏈接到g ++驅動程序,或者您必須顯式鏈接到C++標準庫中。

與G ++鏈接是最簡單的解決辦法,但你也可以嘗試加入-lstdc++作爲庫標誌。

請記住,還有很多與此相關的缺陷。 C++ ABI並不簡單,在編譯器(clang/g ++/etc)或甚至不同版本的GCC中不一定是一致的。如果你的Haskell程序動態鏈接到用另一個C++ ABI編譯的其他C++代碼,這可能是一個問題。

另外請注意,您還必須在C/C++邊界的所有異常。 Haskell期待一個直接的C ABI,並且不能處理通過C/C++邊界泄露的C++異常。

+0

我試着用g ++連接,並得到了相同的結果。但是給GHC作品提供了-lstdC++,這是我沒有想到的。謝謝! – Maxander

0

如果你想在C代碼C++代碼,使用extern "C++"周圍的一切,你的C程序使用C++代碼。然後你可以把它編譯成一個C程序,而Haskell甚至不知道它是在幕後使用一些C++代碼實現的。

編輯:我從來沒有嘗試過這個方向(一般是你用C代碼在C++項目),但基本上這是它如何工作的。

如果它不只是工作,嘗試編譯C++程序一樣相剋的任何普通的C++程序++,然後寫一個使用它的C程序。

0

我會嘗試將extern「C」添加到將用C調用的C++函數中.C++編譯器必須知道函數將由C編譯器使用extern「C」構造來調用。

//在C++代碼

//聲明功能(炭,INT)作爲使用的extern 「C」 C函數: 的extern 「C」 void函數(炭C,INT I);

...

//實現函數(炭,INT)在C++模塊: void函數(炭C,int i)以 { ... }