Krystian
Krystian

Reputation: 3423

Calling Obj-C method from C

I've got a library written in C, where I need to push a call to a method written in Obj-c. I don't want to modify the original code too much, so I decided to create a "bridge" class to handle the calls between C and ObjC:

DRMBridge.h

#ifndef DRMBridge_h
#define DRMBridge_h

#include "DRMBridgeObjC.h"

void bridge_test();


#endif

DRMBridge.c

#import "DRMBridge.h"


void bridge_test() {

    ctest();

 }

Above is compiled as C

Now here's my objc code:

DRMBridgeObjC.h

#ifndef DRMBridgeObjC_h
#define DRMBridgeObjC_h

#import <Foundation/Foundation.h>

@interface DRMBridgeObjC : NSObject

+(void) test;

@end

void ctest();

#endif

DRMBridgeObjC.m

#import "DRMBridgeObjC.h"

@implementation DRMBridgeObjC : NSObject 

+(void) test  {
    NSLog(@"OH YEAH!");
}
@end


void ctest() {
    [DRMBridgeObjC test];
}

Quite simple.

In the C library I want to call my code from I've added: #include "DRMBridge.h" into the .h file and bridge_test(); in .c file.

Now the best part, when I compile I get:

In file included from /Users/krystian/projects/mdb-reader-lib/reader-Include/ios/MDBReader/Class/DRM/DRMBridge.c:5:
In file included from /Users/krystian/projects/mdb-reader-lib/reader-Include/ios/MDBReader/Class/DRM/DRMBridge.h:8:
In file included from /Users/krystian/projects/mdb-reader-lib/reader-Include/ios/MDBReader/Class/DRM/DRMBridgeObjC.h:12:
In file included from /Applications/Xcode64.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator8.4.sdk/System/Library/Frameworks/Foundation.framework/Headers/Foundation.h:8:
/Applications/Xcode64.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator8.4.sdk/System/Library/Frameworks/Foundation.framework/Headers/NSObjCRuntime.h:400:1: error: expected identifier or '('
@class NSString, Protocol;
^
[...]

I went looking, and found this: ios - Parse Issues in NSObjCRuntime, NSZone, and NSObject

However my pch file looks like this:

#import <Availability.h>

#ifndef __IPHONE_5_0
#warning "This project uses features only available in iOS SDK 5.0 and later."
#endif

#ifdef __OBJC__
    #import <UIKit/UIKit.h>
    #import <Foundation/Foundation.h>
#endif

I think the issue I have is that the C compiler tries to compile my ObjC file first, instead of the other way around. I've tried changing the order of files inside Compile Sources to make sure that my .m file is above .c file, but still no go.

Something else I have found which made me lost:

when I follow this answer: https://stackoverflow.com/a/20461780/487605 and change the library itself to .m, and call [DRMBridgeObjC test] code from there - it works.... Compiles fine, no errors given, works fine.

This implies to me, that there's something screwed up with my DRMBridge, but what?

Thanks Krystian

Upvotes: 2

Views: 316

Answers (2)

Cy-4AH
Cy-4AH

Reputation: 4615

DRMBridge.h

#ifndef DRMBridge_h
#define DRMBridge_h

#include <CoreFoundation/CoreFoundation.h> //or put in .pch

CF_EXPORT void bridge_test();

#endif

DRMBridge.m

#import "DRMBridge.h"
#import "DRMBridgeObjC.h"


void bridge_test() {

    ctest(); //or [DRMBridgeObjC test]; if you like

 }

Thats all. And you can include DRMBridge.h in whatever you like: in .c, in .m, in .cpp.

Upvotes: 0

gnasher729
gnasher729

Reputation: 52632

You've seen the solution already. Use #ifdef __ OBJC__ in your Objective-C header file so that only the plain C bits are compiled when including the file from C

Upvotes: 1

Related Questions