Is there any way I could pass an object method instead of a function to a function wanting a SCNetworkReachabilityCallBack as its argument?
Here is how SCNetworkReachabilityCallBack is defined:
typedef void (*SCNetworkReachabilityCallBack) (
SCNetworkReachabilityRef target,
SCNetworkReachabilityFlags flags,
void *info
);
Pass a block that sends the message, then have your C callback execute the block! :D
Basically, the C callback is going to act as glue code. Since an Objective-C method's IMP will never be of a type compatible with the callback, you are always going to need at least one level of indirection before you get to an Objective-C message dispatch. If you need to carry more state than just the object, a block may help you, but that C function stub isn't going anywhere.
To be safe, you could write some C or C++ glue code and pass that function which would then call into your object method.
Related
I have this problem. This the external library that i must use in .h file:
typedef struct _IPCSSContext IPCSSContext;
IPCSSContext * ipcssnew(const IPCSSCfg *_config, const IPCSSCallbacks *_callbacks, void *_user);
How can I use? Thanx
First you define a variable of type IPCSSCallbacks whatever that might be, but it's probably a struct of function pointers.
Then you fill in the fields of the variable with pointers to your callback functions.
Then you call icssnew() passing the IPCSSCallbacks, the config and a pointer to anything you like. This pointer will be passed untouched to your callback functions when they are called and you can do what you like with it in the callbacks (including nothing).
This is a pretty standard pattern in C for performing callbacks.
I have a C function(a callback function in Audio Queue Services) and I want to send message to self. How to do that?
If I type in [self message], there is an error:
Use of undeclared identifier 'self'
You don't perform objc messages in realtime callbacks, such as audio. The reason for this is that objc messaging is not constant time, and may lock, resulting in missed deadlines, resulting in audio dropouts. Static or dynamic (virtual) C++ calls and C function calls are of course constant time, and suitable for realtime contexts.
If it were not an realtime/audio callback, then one option would be to pass self as the user info or context parameter:
void SomeCallback(t_stuff* const stuff, void* userInfo) {
MONClass * Self = (MONClass*)userInfo;
[Self doSomething];
}
self is only meaningful in the context of a class definition -- it's a pointer to an instance of that class. Functions aren't part of any class, so there is no self pointer. If you want your callback to be able to send a message to a given object, you'll need to stash a pointer to that object where your callback can find it. That might be a global variable (ick), a userInfo parameter that's meant for just this sort of thing (much better), or somewhere else.
I have a C struct that contains a function pointer. Now, I have used this setup within C with no problems, but now I'm using this C struct in Objective-C and I need to pass a function (or selector) pointer that is defined in the Objective-C class.
1. Here is what I have for the Objective-C selector that needs to be passed as a pointer to the C function:
- (void)myObjCSelector:(int*)myIntArray
{
// Do whatever I need with myIntArray
}
2. And here is where I run into a wall, Within Objective-C I'm trying to pass the selector as a pointer to the C function call: In place of "myObjCSelectorPointer" I need the proper syntax to pass the selector as a function pointer in this C function call:
passObjCSelectorPointerToCContext(cContextReference, myObjCSelectorPointer);
I did investigate this issue, but could mainly find several different ways of doing similar things, but I couldn't find anything specific for calling C functions and passing an Objective-C selector pointer.
In objc a selector is not a function pointer. A selector is a unique integer that is mapped to a string in a method lookup table stored by the objc runtime. In the above case your method name would be myObjCSelector: and to get the unique selector for it you would type #selector(myObjCSelector:). However this would be of no use to you because it doesnt represent a particular implementation of a function.
What youre looking for is IMP. Refer to this SO question.
EDIT 2:
IMP myObjCSelectorPointer = (void (*)(id,SEL,int*))[self methodForSelector:#selector(myObjCSelector:)];
Then you can call the method using
myObjCSelectorPointer(self,#selector(myObjCSelector:),myIntArray);
However, what this means you will need to make sure that you add the pointer to self in the c function call passObjCSelectorPointerToCContext.
So it should look like this
passObjCSelectorPointerToCContext(cContextReference, self, myObjCSelectorPointer);
when called from within the object that contains the method.
It is important to note though that using IMP is almost never the right technique. You should try to stick with pure Obj-C. Obj-C is quite efficient after the first call to a message because it uses temporal caching.
EDIT 1:
It's useful to understand why objc works in this way. The Apple documents explain it in depth. However a short explanation is as follows:
When you send a message to an object such as [myobject somemethod] the compiler won't immediately know which particular implementation of somemethod to call because there might be multiple classes with multiple overriden versions of somemethod. All of those methods have the same selector, irrespective of its arguments and return values and hence the decision about which implementation of somemethod is deffered to when the program is running. [myobject somemethod] gets converted by the compiler into a C function call:
objc_msgSend(myobject, #selector(somemethod))
This is a special function that searches each myobject class layout to see whether that class knows how to respond to a somemethod message. If not it then searches that class's parent and so on until the root. If none of the classes can respond to somemethod then NSObject defines a private method called forward where all unknown messages are sent.
Assuming that a class can respond to the somemethod message then it will also have a particular pointer of type IMP that points to the actual implementation of the method. At that point the method will be called.
There is considerably more to this procedure than I have described but the outline should be enough to help you understand what the goal of a selector is.
One final point is that the reason method names are mapped to unique integers via the #selector directive is so that the runtime doesn't have to waste time doing string comparisons.
Basically, the answer is: Objective-C selectors are different from function pointers. You need two pieces of data to perform a selector. That is an object and the selector itself. You will need some glue to accomplish your task.
Check this question.
Do you have to use a function pointer? In Objective-C, you can get the function pointer to an arbitrary method implementation (known as an IMP), but this is extremely uncommon, and usually not a good idea. Calling objc_msgSend() directly is also not the greatest idea, because there are several different variants of objc_msgSend(), and the compiler automatically chooses different ones to use based on the return type of the method. Methods that return an object go through objc_msgSend(), but objects that return structs might go through objc_msgSend() or they might go through objc_msgSend_stret(). And if the method returns a double, then it goes through objc_msgSend_fpret()...
Documentation: Objective-C Runtime Reference: Sending Messages
Instead, I might recommend using a target-action pair, or using a block. Then you might do something like:
myContextRef->target = anObjcObject;
myContextRef->action = #selector(invokeMe:);
And when you're done, do:
[myContextRef->target performSelector:myContextRef->action withObject:someReturnInformation];
Or maybe use a block:
myContextRef->completionHandler = [^(id returnInformation) {
[anObjcObject invokeMe:returnInformation];
} copy];
And then when you're done, do:
myContextRef->completionHandler(someReturnInformation);
(and don't forget to -release the block when you free the context)
I have a simple question i.e. how can I pass objective-C function reference as a C function pointer so that C can invoke that function.
edit: Sorry for not providing the sample source here it is:
- (void)init {
CLibStructure cLibObject;
cLibObject.on_work_done = &cWorkDone;
}
the function that will point to on_work_done will have this signature in C
static void cWorkDone(const char *workInfo);
whereas in objective-C this is the signature that I made
- (void) workDoneWithStatusMessage:(const char *message);
Now i want is to point cLib.on_work_done the pointer to objective-c function, if I point to standard C function it works.
In short, you can't. Not directly.
A method call is a combination of a target, the object to message, and the selector that identifies the method to call.
You need to bundle those up together somehow. With Blocks it is easy enough. With pure C APIs, it can typically be done with a context pointer or something like it.
Given that you posted no code, no examples, none of the API to be used, and none of the details about the C API itself, providing details is difficult.
You can create a function that calls the method, and then manipulate a pointer to that:
int function(NSObject *something, int someArg)
{
return [something thisIsAMethod:someArg];
//assuming NSObject has a method called thisIsAMethod that takes an int as a parameter and returns an int.
}
and then you could use a pointer to this function:
int (*pointerToFunction)(NSObject *, int) = &function;
I was going through Apple's documentation and I saw something like this (void (^)(void)). Can somebody explain what this statement means? ^ is XOR, right? void XOR void doesn't makes much sense to me?
There was also something like (void (^)(BOOL finished))
These are blocks which add anonymous functions and function objects to Objective-C. See e.g. Introducing Blocks and Grand Central Dispatch :
Block objects (informally, “blocks”) are an extension to C, as well as Objective-C and C++, that make it easy for programmers to define self-contained units of work. Blocks are similar to — but far more powerful than — traditional function pointers. The key differences are:
Blocks can be defined inline, as “anonymous functions.”
Blocks capture read-only copies of local variables, similar to “closures” in other languages
Declaring a block variable:
void (^my_block)(void);
Assigning a block object to it:
my_block = ^(void){ printf("hello world\n"); };
Invoking it:
my_block(); // prints “hello world\n”
Accepting a block as an argument:
- (void)doSomething:(void (^)(void))block;
Using that method with an inline block:
[obj doSomeThing:^(void){ printf("block was called"); }];
That's a block, an Apple-specific extension to C, similar to function pointers, or function objects in other languages.
(void (^)(void)) looks like a typecast to the type of a block that takes no parameters and returns nothing. Similarly, (void (^)(BOOL finished)) looks like another typecast, to a block with one boolean parameter and returning nothing.