4

I have a c++ class that needs to call an objective c method using a pointer to that method. This method returns void and takes an argument of type 'status' where status is a simple integral enum.

 enum status
 {
       status_valid = 0,
       status_invalid,
       status_unknown
 };

I have the pointer to the obj-c method set up like this. The pointer to the method is also being passed to the c++ class and

typedef void (*FuncPtr) (status);
FuncPtr myObjCSelectorPointer = (void (*)(status))[self methodForSelector:@selector(statusChanged: )];
cppClassInstance->setFuncPointer(myObjCSelectorPointer)

myObjCSelectorPointer is being held on to by the cppClass like this:

void cppClass::setFuncPointer(FunctPtr *ptr)
{
     this->funcPtr = ptr;
}

Now somewhere else, when I try to call the method pointed to by this pointer, like this:

status s;
funcPtr(s);

The method gets called correctly, but the value passed into the method is lost. The obj-c method receives a completely random value. When I try to call a method in the cpp class using the same way, it passes and receives the correct value.

What am I doing wrong? Can you not call an objective c method like this?

3
  • Post the status definition, I am guessing but try passing the status by reference Commented May 14, 2013 at 18:41
  • I added the status definition to the post. Also, I have tried to pass it by reference, but that didnt work either. I had the same problem with that, too. Commented May 14, 2013 at 18:43
  • @halfwaythru Your function prototype is wrong - see my answer. Commented May 14, 2013 at 18:44

1 Answer 1

6

The problem is that the function signature of Objective-C methods is not as simple as you might think.

In order to make object-oriented programming possible, Objective-C methods take two implicit arguments: id self, SEL _cmd, the calling object and the selector sent - these need to be passed. You will need to get an object to call the method on, and you should store the selector too. Then, change your function type definition to the correct one:

typedef void (*FuncPtr) (id, SEL, status);

To be read: [1], [2] (near the part typedef id (*IMP)(id, SEL, ...))

Sign up to request clarification or add additional context in comments.

10 Comments

This sounds useful, but two things: 1.) If the function prototype is incorrect, then shouldn't it result in the function not getting called? My obj-c method is getting called just fine with this prototype. 2.) When I try to change the function ptr prototype, I need to include it in a C++ header where 'id' is an undeclared identifier. How do I circumvent that?
@halfwaythru 1. Why should it result in the function not getting called? The CALL instruction is emitted by the compiler just fine... 2. Compile as Objective-C++.
@halfwaythru 1) no. it will still be called, and it could result in undefined behavior. 2) the objc runtime is C -- #include <objc/objc.h> or as H2CO3 said a moment earlier, you could also compile it as objc++.
@justin (and I didn't even mention the case of fpret and stret functions, where the calling convention is again something else... I <3 inconsistencies...)
@H2CO3 yea. personally, i'd just compile that file as objc++ and let the compiler do the legwork for me.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.