2012-01-11 76 views
0

我想在C鏈接的共享庫中使用一些C++類。我有以下問題。C鏈接和C++頭文件

如果

#include <iostream> 
extern "C" 
{ 
void f(){} 
} 

編譯併成功地鏈接,但F()不能在導致庫中找到。

如果

extern "C" 
{ 
#include <iostream> 
void f(){} 
} 

我得到了很多的編譯器錯誤(只是不知道如何用英語,一些關於C鏈接模板正確地翻譯它們)iostream中對C++的關鍵字「模板」的每一次出現,其中包括報頭。

應該做什麼?

回答

4

第一個變體是正確的。只有存在於C中的東西才能在extern "C"塊中聲明,而模板和類當然不屬於該類別。如果您使用的是C++編譯器,則只需確保您的函數在頭文件中也聲明爲extern "C"。這通常通過書寫

#ifdef __cplusplus 
// C++ declarations (for example classes or functions that have C++ objects 
//     as parameters) 

extern "C" 
{ 
#endif 

// C declarations (for example your function f) 

#ifdef __cplusplus 
} 
#endif 

在標題中。

+0

謝謝。它工作完美。 – Alexander 2012-01-11 10:16:18

0

使用__declspec導出函數,類等等...... 另外:http://msdn.microsoft.com/en-us/library/a90k134d(v=vs.80).aspx

而這一次是非常好的:http://www.flounder.com/ultimateheaderfile.htm

+0

這是不可移植的,OP沒有說他使用了什麼編譯器。 – filmor 2012-01-11 10:06:36

+0

是的,忘了說。我使用gcc 4.6.1和Linux。 – Alexander 2012-01-11 10:17:28

+0

您不必使用declspec(即使在Windows上),並且通過使用extern「C」,它與其他C++編譯器以及可能的C代碼本身交叉兼容。 如果這是在Windows平臺上構建的,那麼您將使用.def文件在導出表中聲明該符號。 – CashCow 2012-01-11 12:12:20

2

首先是正確的;系統標頭(以及大多數其他標頭) 只能包含在全局範圍內,不包括任何名稱空間,類,功能或鏈接規範塊。有在 <iostream>容易的事情,不會在extern "C"是合法的,即使 有沒有,名字改編爲extern "C"幾乎可以肯定是從C++的 不同,庫本身是肯定編譯 爲extern "C++"

你是怎麼定義f的?這可能是一個類似的問題:如果源 文件將其編譯爲extern "C++"函數,則名稱將爲 與編譯爲 和extern "C"函數的客戶端文件不同。

這裏的一般政策是處理頭和功能,你通常會做同樣的方式 定義/聲明,除了 可以確保頭可以被包含在C和C++源代碼, 如:

#if __cplusplus 
extern "C" { 
#endif 
void f(); 
// Other `extern "C"` functions... 
#if __cplusplus 
} 
#endif 

然後包括在所有文件此頭其中函數f()被使用, 並且其中它被定義在文件中。