2011-12-24 109 views
1

我增加了行extern "C" void perlinTest(void);到C++頭隨着包括C頭文件,希望這是所有我需要的,但編譯器會抱怨的:如何從iPhone的C++代碼中調用C函數?

Undefined symbols for architecture i386: 
    "perlinTest()", referenced from: 
     CreateRenderer3(IResourceManager*) in Renderer.o 
+1

您還需要鏈接任何庫提供的功能。 – Mat 2011-12-24 20:46:41

+0

這不是圖書館。我寫了c函數和調用它的C++代碼。 – Xavier 2011-12-24 20:49:04

+0

然後,您需要確保C代碼已編譯並與您的C++代碼鏈接。 – Mat 2011-12-24 20:50:49

回答

1

您的C++代碼需要知道該函數是C函數。要做到這一點,你需要這樣聲明它:

extern "C" [prototype]; 

您的具體情況現實的例子是:

extern "C" void perlinTest(); 

這樣做的原因是,C++ function names are mangled的東西,講述的類型參數。在最底層,這是允許重載的:它有兩個可見的符號共享相同的名字是不合法的,所以C++通過在函數名稱中嵌入指示參數類型的標記來允許它們。例如,void perlinTest()在我的Lion box上被_Z10perlinTestv改爲g++(可能是clang++),雖然這是ABI特有的,並不一定在其他平臺上相同。

但是,C不支持重載,並且函數不受名稱的限制,所以當C++代碼試圖調用它時,它需要知道它不能使用重名。這是extern "C"告訴編譯器。

如果您的頭文件需要從C和C可讀++時,通常的做法是將它們包裝在一個extern "C"塊(extern "C" { /* declarations */ })本身包裹在一個#ifdef __cplusplus預處理器指令(因此C代碼不會看到extern "C"碼)。

#ifdef __cplusplus 
extern "C" { 
#endif 

/* header body */ 

#ifdef __cplusplus 
} 
#endif 
0

如果它不是一個庫,你不需要任何extern C.我將轉向.c文件擴展名,以及如何將您的編譯器配置爲識別它(看起來不像.c代碼)

0

您是否確實在任何地方實施了void perlinTest(void)

最初,您可能只需聲明函數而不必實際執行它。如果沒有其他類/對象實際調用perlinTest(),Xcode將很樂意構建和運行您的應用程序,而不會發出任何錯誤。由於perlinTest()實際上並未從任何地方引用,因此它並不關心該函數是否未實際實現。

只要您嘗試從其他類中的其中一個類中調用perlinTest()(例如從CreateRenderer3(IResourceManager*) in Renderer.o),鏈接器將希望確定該符號可以被解析,並且如果您沒有實際實現它的準系統定義(見下文),那麼你可能會得到一個像你得到的錯誤。

最小實現類似下面應防止連接錯誤:

void perlinTest(void) { 

} 
+0

是的,我已經實施。 – Xavier 2011-12-24 21:10:19

0

一個竅門,你可以用它來調試,這是在你的perlinTest()功能引入故意的錯誤。然後構建您的應用並查看編譯器是否報告錯誤。如果應用程序編譯無論如何,那麼你的問題是,具有此功能的文件不是你正在構建的目標的一部分。

另請注意,您粘貼的錯誤是針對i386架構的,因此它不能是iPhone。相反,您可能正在爲iPhone模擬器構建。

編輯:下一步是檢查由Xcode發出的鏈接命令是否包含具有C函數的.o。如果確實如此,那麼您應該使用nm工具轉儲.o文件的內容,以查看.o中函數名稱的外觀。

+0

包含perlinTest的文件在引入錯誤後未編譯。 – Xavier 2011-12-24 22:37:23

+0

是的,我正在編譯iPhone模擬器。 – Xavier 2011-12-24 22:37:53