我增加了行extern "C" void perlinTest(void);
到C++頭隨着包括C頭文件,希望這是所有我需要的,但編譯器會抱怨的:如何從iPhone的C++代碼中調用C函數?
Undefined symbols for architecture i386:
"perlinTest()", referenced from:
CreateRenderer3(IResourceManager*) in Renderer.o
我增加了行extern "C" void perlinTest(void);
到C++頭隨着包括C頭文件,希望這是所有我需要的,但編譯器會抱怨的:如何從iPhone的C++代碼中調用C函數?
Undefined symbols for architecture i386:
"perlinTest()", referenced from:
CreateRenderer3(IResourceManager*) in Renderer.o
您的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
如果它不是一個庫,你不需要任何extern C.我將轉向.c文件擴展名,以及如何將您的編譯器配置爲識別它(看起來不像.c代碼)
您是否確實在任何地方實施了void perlinTest(void)
?
最初,您可能只需聲明函數而不必實際執行它。如果沒有其他類/對象實際調用perlinTest()
,Xcode將很樂意構建和運行您的應用程序,而不會發出任何錯誤。由於perlinTest()
實際上並未從任何地方引用,因此它並不關心該函數是否未實際實現。
只要您嘗試從其他類中的其中一個類中調用perlinTest()
(例如從CreateRenderer3(IResourceManager*) in Renderer.o
),鏈接器將希望確定該符號可以被解析,並且如果您沒有實際實現它的準系統定義(見下文),那麼你可能會得到一個像你得到的錯誤。
最小實現類似下面應防止連接錯誤:
void perlinTest(void) {
}
是的,我已經實施。 – Xavier 2011-12-24 21:10:19
一個竅門,你可以用它來調試,這是在你的perlinTest()
功能引入故意的錯誤。然後構建您的應用並查看編譯器是否報告錯誤。如果應用程序編譯無論如何,那麼你的問題是,具有此功能的文件不是你正在構建的目標的一部分。
另請注意,您粘貼的錯誤是針對i386架構的,因此它不能是iPhone。相反,您可能正在爲iPhone模擬器構建。
編輯:下一步是檢查由Xcode發出的鏈接命令是否包含具有C函數的.o。如果確實如此,那麼您應該使用nm工具轉儲.o文件的內容,以查看.o中函數名稱的外觀。
您還需要鏈接任何庫提供的功能。 – Mat 2011-12-24 20:46:41
這不是圖書館。我寫了c函數和調用它的C++代碼。 – Xavier 2011-12-24 20:49:04
然後,您需要確保C代碼已編譯並與您的C++代碼鏈接。 – Mat 2011-12-24 20:50:49