我有一个在C语言中执行的函数。当满足某个特定条件时,我想要改变一个UIButton的状态。我试图使用dispatch NSNotification来实现,但没有成功。
如何从C函数向Obj-C对象发送消息?
理想情况下,我希望能够以某种方式使用NSNotification。
我有一个在C语言中执行的函数。当满足某个特定条件时,我想要改变一个UIButton的状态。我试图使用dispatch NSNotification来实现,但没有成功。
如何从C函数向Obj-C对象发送消息?
理想情况下,我希望能够以某种方式使用NSNotification。
C代码需要放在.m文件中。如果不是,则在.m文件中添加一个C回调函数,该函数可以为您发布通知或执行其他操作。以下是访问调用位于.m文件之外的C函数的Objective-C类的示例。
//SomeCCode.c
void someCFunction(int somevar, void (callback) (void*) , void *context)
{
doSomething(somevar);
callback(context);
}
//SomeClass.m
void someCCallbackInObjC(void *context)
{
SomeClass *myclass = (SomeClass*)context;
//Access my class or just post notification
}
@implementation SomeClass
...
-(void)someMethod
{
someCFunction(0, someCCallbackInObjC, self);
}
...
@end
只需将您的C文件编译为Objective-C,并像往常一样访问NSNotificationCenter。
与C ++不同,Objective-C对C代码没有兼容性问题。只要使用的底层标准相同,所有C代码也是有效的Objective-C代码。
编辑:详细说明:只要使用Objective-C编译器,在方法和函数中可以做的事情没有区别,除了在C函数中不能使用self
和super
,除非您自己定义它们。
重新编辑:为了在C函数中定义self,只需按以下方式定义:
notifyingFunction(id self, /* other arguments */);
在调用函数时,传递任何适当的self
参数。
我花了很长时间来寻找一种方法,在我的使用XCode 5开发的OS X应用程序中,从C向Objective C发布通知的解决方案。Joe's answer是我在Mavericks上使用XCode 5的唯一有效解决方案。虽然我不得不添加桥接,但是我的应用程序具有类似以下代码的功能:
//SomeCCode.c - no changes here
void someCFunction(int somevar, void (callback) (void*) , void *context)
{
doSomething(somevar);
callback(context);
}
//SomeClass.m
void someCCallbackInObjC(void *context)
{
// change #1: added __bridge in type cast
SomeClass *myclass = (__bridge SomeClass*)context;
//Access my class or just post notification
}
@implementation SomeClass
...
-(void)someMethod
{
// change #2: added the type cast with __bridge for self
someCFunction(0, someCCallbackInObjC, (__bridge void*) (self));
}
...
@end
我在这方面折腾了很多,所以
额外补充一下:
我正在使用一个C单元,我不想将其重命名为*.m文件。而且我需要从那里调用一个日志。
没有包装器可以帮助我避免链接器错误。
因此,我使用了以下模式:
我制作了hpp和cpp文件
在头文件中添加了一个extern变量-指向函数的指针:
extern void (*transLogFun) (const char *,...);
并将其定义返回到cpp文件中
void (*transLogFun) (const char *,...) = NULL;
然后我创建了一个h和mm文件: h:
#import <UIKit/UIKit.h>
#import "fff.hpp"
void ioslogfun(const char *s, ...);
#import "zzz.h"
#import <Foundation/Foundation.h>
void ioslogfun(const char *s, ...){
va_list vl;
va_start(vl,s);
char *str;
vasprintf(&str,s,vl);
va_end(vl);
NSLog([NSString stringWithUTF8String:str]);
free(str);
}
class Fff{
public:
Fff(){
transLogFun = &ioslogfun;
}
};
Fff initiator;
无论我在哪里调用transLogFun(...),它都能正常工作。