4

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).

1
  • 1
    You only need to change files that actually include Objective-C code to .mm. If all the other files go through your C++ wrapper and its header does not include any Objective-C that is visible to them, they don't need to become Objective-C++. Commented Feb 21, 2013 at 19:22

4 Answers 4

2

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();
Sign up to request clarification or add additional context in comments.

1 Comment

Although I used a slightly different implementation (A bit complicated to provide an example since its mostly the way in which I included files) I ended up using a bridge of sorts to deal with the issue, using C bridging functions to access the Obj-C methods and this example helped me on my way. Thanks!
2

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.

1 Comment

Sorry, forgot to mention I've already tried this. i will edit the question to clarify this.
1

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.

Comments

1

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;
}

2 Comments

Since Objective-C++ has a few incompatibilities with normal C++ and takes longer to couple, it might not be desirable to switch a whole codebase over like that.
I agree--wasn't necessarily suggesting that. In my little example I changed the main to ObjC++, but you can certainly do it on a module-by-module basis as well -- I do that all the time.

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.