从C调用Cocoa API

Mr *_*eph 12 c macos cocoa

我不知道这是否可行,但是在普通C中使用代码,是否可以从中调用Cocoa API?
有点像#include <cocoa.h>,添加相应的库并去寻找它?

谢谢您的帮助

ugh*_*fhw 14

如果链接到Cocoa或Foundation框架,则可以在C代码中使用objective-c.但是,如果要使用常规消息传递语法,则必须将文件扩展名从.c更改为.m,以便将其编译为objective-c.如果你保持.c扩展名,你将只能使用C风格的运行时调用与目标对象(即互动objc_msgSend,objc_getClass等等).

示例:在.m文件中

void cFunction() {
    [[NSString alloc] init];
}
Run Code Online (Sandbox Code Playgroud)

在.c文件中

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

如果选择第二种方法,请参阅Objective-C运行时参考.

  • 通常,调用`objc_msgSend` as-is是错误的.你应该将它转换为适当的函数类型:`typedef CFStringRef(*StringWithStringIMP)(id,SEL,CFStringRef); CFStringRef string =((StringWithStringIMP)objc_msgSend)(objc_getClass("NSString"),sel_getUid("foo"),CFSTR("这是没有意义的.")); (4认同)
  • @MrAleph:我强烈建议不要使用`.c`文件中的`objc_msgSend`.只需使用`.m`即可.您可以使用`gcc foo.m -o foo.o -framework Foundation -framework Cocoa`等编译没有XCode的`.m`文件. (3认同)

Yuj*_*uji 5

Objective-C 是 C 之上的一个非常薄的包装器。编译器只是翻译

 [obj message:argument];
Run Code Online (Sandbox Code Playgroud)

进入 C 调用

 obj_msgSend(obj,@selector(message:),argument);
Run Code Online (Sandbox Code Playgroud)

就是这样(其中@selector(message:)有一个神奇的编码将选择器(方法名称)变成计算机可以理解的东西。)

因此,从编译器的角度来看,Objective-C 和 C 之间没有太大区别。例如,您可以使用 Objective-C 编译器编译纯 C 程序,其结果与使用 C 编译器编译得到的结果完全相同。

因此,将 Objective-C 与 C 进行“混合”的最简单方法是使用.m扩展,以便编译器使用 Objective-C。

这并不会让你的程序突然变得非常 Objective-Cy。您可以使您的程序几乎是纯 C 的,扩展名为.m. 使用.m,您可以毫无问题地添加几行 Objective-C 消息调用。