tusharfloyd
tusharfloyd

Reputation: 1972

Calling Objective-C method from C++ function?

I picked this up from an answer to a question on how to call objective-c method from C++ method

This runs fine.

MyObject-C-Interface.h

 #ifndef __MYOBJECT_C_INTERFACE_H__
 #define __MYOBJECT_C_INTERFACE_H__ 1

 int MyObjectDoSomethingWith (void *myObjectInstance, void *parameter);

 #endif

MyObject.h

#import "MyObject-C-Interface.h"

@interface MyObject : NSObject
{
     int someVar;
}

- (int) doSomethingWith:(void *) aParameter;
@end

MyObject.mm

 #import "MyObject.h"

 @implementation MyObject

 int MyObjectDoSomethingWith (void *self, void *aParameter)
 {
     return [(id) self doSomethingWith:aParameter];
 }

 - (int) doSomethingWith:(void *) aParameter
 {
     // ... some code
     return 1;
 }

 @end

MyCPPClass.cpp

#include "MyCPPClass.h"
#include "MyObject-C-Interface.h"

int MyCPPClass::someMethod (void *objectiveCObject, void *aParameter)
{
     return MyObjectDoSomethingWith (objectiveCObject, aParameter);
}

NOW if i use something like

MyObject-C-Interface.h

 #ifndef __MYOBJECT_C_INTERFACE_H__
 #define __MYOBJECT_C_INTERFACE_H__ 1

 @class MyObject;

 int MyObjectDoSomethingWith (MyObject* myObjectInstance, void *parameter);

 #endif

My question is instead of using void *myObjectInstance if i use MyObject *myObjectInstance.

it gives this error
error: expected unqualified-id [1] : @class line and
error: use of undeclared identifier 'MyObject' [3] in function prototype's line

Help!!!!

Upvotes: 2

Views: 4309

Answers (1)

pmdj
pmdj

Reputation: 23428

Link Error:

The link error is to do with the way C++ mangles function names, which C doesn't do. This actually has nothing to do with Objective-C. Specifically,

int MyObjectDoSomethingWith (void *myObjectInstance, void *parameter);

in C or Objective-C (on OSX) is exported to the linker using the name _MyObjectDoSomethingWith. A function with the same name and prototype, compiled with a C++ or Objective-C++ compiler, is known to the linker as __Z23MyObjectDoSomethingWithPvS_. This is called "name mangling", and it encodes the parameter types. Otherwise, function overloading wouldn't work, as functions with different parameter types but the same name couldn't be distinguished. To call a function defined in C from C++, you therefore have to mark the prototype such that C linkage is expected, and it won't mangle the name of that specific overload of the function.

You'll need to tell the C++ compiler to treat it as a C function using extern "C", either like this:

#ifndef MYOBJECT_C_INTERFACE_H
#define MYOBJECT_C_INTERFACE_H

#ifdef __cplusplus
extern "C" {
#endif

int MyObjectDoSomethingWith (void *myObjectInstance, void *parameter);

#ifdef __cplusplus
}
#endif

#endif

or like this:

#ifndef MYOBJECT_C_INTERFACE_H
#define MYOBJECT_C_INTERFACE_H

#ifdef __cplusplus
#define CFUN extern "C"
#else
#define CFUN
#endif

CFUN int MyObjectDoSomethingWith (void *myObjectInstance, void *parameter);

#endif

@class declaration compile error (please do not ask more than one question at a time):

You're trying to #include "MyObject-C-Interface.h", which contains an Objective-C @class forward declaration, from MyCPPClass.cpp, which will be compiled as pure C++. Objective-C directives are mostly syntax errors in C++, so you can't do that. To pass around Objective-C objects in pure C++ or C, you will need to use the id type. You'll need to #include <objc/objc.h> for that, as id isn't defined by default in C or C++.

*Also, please don't prefix your names with two underscores: __ - such names are reserved.*

Upvotes: 4

Related Questions