user2087530
user2087530

Reputation: 125

Using an Objective-C Class in C++

I'm fairly new to Objective-C and I am building an iCloud utility library for our project. I have created an iCloud utility class in Objective-C. I've noticed there are loads of questions on using C++ classes in Objective-C but few the other way around. The problem is, our project (and engine on top of which our project is built) is entirely written in C++ and as such, the objective-c icloud class I have written needs to be accessable from a C++ interface I am writing.

Here is an example:

iCloudUtils.h

#import <Foundation/Foundation.h>

@interface iCloudUtil : NSObject
@property(nonatomic, assign, getter=isAvailable) BOOL iCloudIsAvailable;

@property (assign) NSString *urlToFile;

-(bool) init_iCloud;
-(void) loadDocument: (NSString*)fileUrl;
@end

iCloudUtils.m

#import "iCloudUtil.h"
@synthesize urlToFile = _urlToFile;
@synthesize iCloudIsAvailable = _iCloudIsAvailable;
//////////////////////////////////////////////////////


@implementation iCloudUtil
-(bool) init_iCloud{
//blah blah
}

-(void) loadDocument: (NSString*)fileUrl{
//more blah blah
}

@end

The C++ class I'm attempting to use this from is like so:

iCloudInterface.h

#ifndef __ICloudInterface__
#define __ICloudInterface__

class ICloudInterface {

    static ICloudInterface *_instance;
    bool iCloudIsAvailable;

public:
    ICloudInterface();
    ~ICloudInterface();

    bool init_iCloud();
};

#endif 

What I want to do is to be able to create an instance of iCloudUtils in my C++ class, but I can't #include it in my c++ class without getting 200+ errors about "Stray '@' in program". I'm very inexperienced with Objective-C and even less so with mixing it with C++ so could someone help me out with advice on how to achieve this?

Edit: Just to clear it up, i have already attempted to rename the .cpp to .mm but this hasn't fixed the problem.

Edit2: Also, from what I have understood with reading up (please correct me if I am wrong) by changing a file to .mm, any file that includes it must also change to .mm. I can't do this since it would require changing a very very large number of files to suit a single optional class (reminder that this project and its engine are ALL c++ and this is a cross-platform engine and project).

Upvotes: 4

Views: 2904

Answers (4)

escrafford
escrafford

Reputation: 2393

Switch your .cpp filenames to .mm - this takes it from c++ to objective-c++. Then you'll be compiling a language that understands the header.

Upvotes: 2

jstevenco
jstevenco

Reputation: 2953

Sure -- you can do this. The main thing that's required is to set the .CPP file as "Objective-C++ Source" -- the ".mm" convention is an automagic nicety, but not required. You can then mix and match pretty much as you please:

#import <Foundation/Foundation.h>
#include <iostream>

@interface iCloudUtil : NSObject
@property(nonatomic, assign, getter=isAvailable) BOOL iCloudIsAvailable;
@property(assign) NSString *urlToFile;
- (bool) init_iCloud;
- (void) loadDocument:(NSString*)fileUrl;
@end

//////////////////////////////////////////////////////
@implementation iCloudUtil

@synthesize urlToFile = _urlToFile;
@synthesize iCloudIsAvailable = _iCloudIsAvailable;

- (bool) init_iCloud {
    NSLog(@"init_iCloud");
    std::cout << "i can mix std c++ in here as well\n";
    return YES;
}

- (void) loadDocument:(NSString*)fileUrl {
    NSLog(@"url is %@",fileUrl);
}

@end
//////////////////////////////////////////////////////

class ICloudInterface {
    static ICloudInterface* _instance;
    bool iCloudIsAvailable;
    iCloudUtil* myCloudUtil;
public:
    ICloudInterface();
    ~ICloudInterface();

    bool init_iCloud();
};

ICloudInterface::ICloudInterface() {
    std::cout << "ICloudInterface::ctor\n";
    myCloudUtil = [[iCloudUtil alloc] init];
    [myCloudUtil init_iCloud];
    [myCloudUtil loadDocument:@"file://foo/bar/baz"];
}

ICloudInterface::~ICloudInterface() {
    [myCloudUtil release], myCloudUtil = nil;
    std::cout << "ICloudInterface::dtor\n";
}

int main(int argc, const char * argv[]) {
    std::cout << "Test objc/objc++\n";
    ICloudInterface iface;
    return 0;
}

Upvotes: 1

Guru
Guru

Reputation: 22042

You can't use Obj.C class objects in C++ file with file extension .cpp

You can use c++ class in Obj.C class with extension .mm

To communicate between C++ & Obj.C class, write helper c++ class in .mm file

Say:

  interface iCloudUtil : NSObject  // in .m file
  class ICloudInterface            //in cpp file.

You can take bridge class help to communicate between cpp class in .cpp file to obj.C class in .m file.

//include iCloudUtil.h only in ICloudBridge.mm file.

class ICloudBridge {

    static ICloudBridge *_instance;

public:
    ICloudBridge();
    ~ ICloudBridge();

    ICloudBridge *sharedICloudBridge();
    void loadDocument();
};

void  ICloudBridge:: loadDocument()
{
   iCloudUtil *obj = [iCloudUtil alloc] init] autorelese];
   [obj  loadDocument:@"DocName"];
}

in ICloudInterface.cpp

ICloudBridge *bridge = ICloudBridge::sharedICloudBridge();
bridge-> loadDocument();

Upvotes: 2

Ravindra Bagale
Ravindra Bagale

Reputation: 17655

I think you have to use .mm extension instead of .m extension in the source code filename, or set the file to compile as Objective-C++ in Xcode.

Upvotes: 1

Related Questions