2011-05-05 41 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