简体   繁体   中英

Call obj-c object from a c function

I have a function that executed in c. When a certain condition is met I want to change the state of a UIButton. I was trying to dispatch an NSNotification but that doesnt work.

What would be a good way to send a message to an obj-c object from ac function?

Ideally I would like to somehow be able to use NSNotification

The C Code needs to be inside of a .m file. If it is not then add a C callback function inside your .m that can post your notification or do something else for you. Here is an example of accessing the Objective-C class that calls a C function outside of a .m file.

//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

Simply compile your C files as Objectice-C; and access NSNotificationCenter as usual.

Unlike C++, Objective-C imparts no compatibility pitfalls on C code. All and any C code is also valid Objective-C code, assuming the underlying standard used is the same.

Edit: To elaborate: as long as you use the Objective-C compiler; there's no difference between what you can do in a method and a function; except that self and super aren't available for use in C functions unless you define them yourself.

Reedit: In order to define self in a C function; simply define it as follows:

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

and pass any appropriate self when calling the function.

I've spent quite a while to find the solution to post notifications from C to Objective C for my OS X app developed with XCode 5 on Mavericks. Joe's answer was the only working solution for me with XCode 5 on Mavericks. I had to add bridging though. So, my app has code similar to the following:

//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

I was messing around a lot with this so
just in addition:
I am using ac unit, which i don't want to rename to *.m files. And I need a log called from there.
No wrappers could help me to avoid linker errors.
So I used the following pattern:
I made hpp and cpp files Added an extern variable - pointer to a function to header:

extern void (*transLogFun) (const char *,...);

and its definition to cpp file

void (*transLogFun) (const char *,...) = NULL;

Then i created an h and mm file: h:

#import <UIKit/UIKit.h>
#import "fff.hpp"

void ioslogfun(const char *s, ...);

In mm file i wrote a function and a class with its object like this:

#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;

And where-ever i called the transLogFun(...) it worked fine.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM