2011-05-05 49 views
8

我不知道這是否可行,但以普通C語言編寫代碼,是否可以從它調用Cocoa API?
#include <cocoa.h>之類的東西,添加相應的庫,去吧?從C調用Cocoa APIs

感謝您的幫助

回答

12

如果您對可可或基金會的框架鏈接,您可以在C代碼中使用的Objective-C。但是,如果要使用常規消息傳遞語法,則必須將文件擴展名從.c更改爲.m,以便將其編譯爲objective-c。如果保留.c擴展名,則只能使用c樣式運行時調用與目標對象(即objc_msgSendobjc_getClass等)進行交互。

例子:在一個.m文件

void cFunction() { 
    [[NSString alloc] init]; 
} 

在.c文件

void cFunction() { 
    void* cls = objc_getClass("NSString"); 
    void* obj = objc_msgSend(cls, NSSelectorFromString(CFSTR("alloc"))); 
    obj = objc_msgSend(obj, NSSelectorFromString(CFSTR("init"))); 
} 

如果你選擇了第二種方法,請參閱Objective-C Runtime Reference

+4

通常情況下,調用'objc_msgSend'是錯誤的。您應該將其轉換爲適當的函數類型:'typedef CFStringRef(* StringWithStringIMP)(id,SEL,CFStringRef); CFStringRef string =((StringWithStringIMP)objc_msgSend)(objc_getClass(「NSString」),sel_getUid(「foo」),CFSTR(「This is noless。」));' – 2011-05-05 17:42:48

+0

Cool。我該怎麼做呢?我如何鏈接Cocoa或Foundation框架?它在項目級別嗎?我可以'包括'它嗎?我想繼續只有簡單的C文件和一個Makefile來編譯它並鏈接它(不依賴於XCode來完成) – 2011-05-05 17:47:57

+1

@MrAleph你需要告訴GCC鏈接到框架。使用'-Xlinker -framework -Xlinker Foundation'來執行此操作。您應該執行#include 來獲取當前的運行時頭文件。 – ughoavgfhw 2011-05-05 18:06:24

4

目的-C是C的頂部上的非常薄的包裝器,編譯器只是平移

[obj message:argument]; 

成C-調用

obj_msgSend(obj,@selector(message:),argument); 

,這就是它(其中@selector(message:)是魔法編碼將選擇器(方法名稱)轉換成計算機可理解的東西)。

因此,Objective-C和C之間的編譯器觀點。例如,您可以使用Objective-C編譯器編譯純C程序,其結果與使用C編譯器編譯時得到的結果完全相同。因此,將Objective-C與C混合的最簡單方法是使用.m擴展,以便編譯器使用Objective-C。

這並不會讓你的程序突然變得很Objective-C-y。你可以保持你的程序幾乎純C,擴展名爲.m。通過.m,您可以添加幾行Objective-C消息調用而不會出現任何問題。

+0

我能編寫一個簡單的Makefile來編譯和鏈接它嗎? – 2011-05-05 17:51:20