从c函数调用obj-c对象

3

我有一个在C语言中执行的函数。当满足某个特定条件时,我想要改变一个UIButton的状态。我试图使用dispatch NSNotification来实现,但没有成功。

如何从C函数向Obj-C对象发送消息?

理想情况下,我希望能够以某种方式使用NSNotification。

4个回答

5

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

2

只需将您的C文件编译为Objective-C,并像往常一样访问NSNotificationCenter。

与C ++不同,Objective-C对C代码没有兼容性问题。只要使用的底层标准相同,所有C代码也是有效的Objective-C代码。

编辑:详细说明:只要使用Objective-C编译器,在方法和函数中可以做的事情没有区别,除了在C函数中不能使用selfsuper,除非您自己定义它们。

重新编辑:为了在C函数中定义self,只需按以下方式定义:

notifyingFunction(id self, /* other arguments */);

在调用函数时,传递任何适当的self参数。


这正是我遇到的问题,我不知道如何定义self以在C函数中使用。 - dubbeat
请记住,C函数是静态的,不具有任何类实例的知识。这就是为什么您需要向C函数传递信息,例如上下文的原因。 - Joe
如果C函数是来自C库的回调函数,那么我们如何在.m文件中访问该回调C函数内部的self呢? - jkr

1

我花了很长时间来寻找一种方法,在我的使用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

0

我在这方面折腾了很多,所以
额外补充一下:
我正在使用一个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, ...);

在我的mm文件中,我编写了一个函数和一个类及其对象,就像这样:
#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(...),它都能正常工作。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接