Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can't find standard C++ includes when using C++ class in Cocoa project

I have a Cocoa project (a Mac OS X app), all Objective-C. I pulled in one C++ class (which I know works) from another project, and make an Objective-C wrapper for it. The ObjC wrapper class is using a .mm extension. However, the C++ header file contains #includes to standard C++ header files (<vector>, for example), and I get errors on those.

A minimal example would look like the following. CppClass is the C++ class, and CppWrapper is the ObjC class which wraps it.

//  CppClass.h
#ifndef _CPP_CLASS_H_
#define _CPP_CLASS_H_

#include <vector>

class CppClass
{
public:
    CppClass() {}
    ~CppClass() {}

private:
    std::vector<int> my_ints;
};
#endif /* _CPP_CLASS_H_ */

//  CppWrapper.h
#import <Foundation/Foundation.h>
#import "CppClass.h"

@interface CppWrapper : NSObject {
    CppClass* myCppClass;
}
@end

//  CppWrapper.mm
#import "CppWrapper.h"

@implementation CppWrapper

- (id)init
{
    self = [super init];
    if (self) {
        myCppClass = new CppClass;
    }    
    return self;
}

- (void)dealloc
{
    delete myCppClass;

    [super dealloc];
}

@end

// The file that uses CppWrapper
//  TestAppDelegate.m

#import "TestAppDelegate.h"
#import "CppWrapper.h"

@implementation TestAppDelegate
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
    myWrapper = [[CppWrapper alloc] init];
}
@end

The error I'm getting is the #include of vector in CppClass.h. The error is

lexical or Preprocessor issue: 'vector' file not found

This code works fine in another (all C++) project, so I'm pretty sure it's a build setting, or something I've done wrong in the wrapper class. I'm using Xcode 4. I created a default Cocoa Mac OS app project and all settings are default.

Update: I just realized that if I set TestAppDelegate's File Type to Objective-C++ (or rename it to TestAppDelegate.mm), it works. What I don't understand is, this class is pure Objective-C; why does it have to be compiled as Objective-C++? The whole point of having an Objective-C wrapper on my C++ class is so that I don't have to build the entire project as Objective-C++.

like image 341
zpasternack Avatar asked May 21 '11 18:05

zpasternack


1 Answers

The problem with your CppWrapper class is that it doesn't present a pure Objective-C interface. In your CppWrapper.h file, you're importing the C++ class's header file, which means that any Objective-C class that imports the wrapper class will need to be compiled as Objective-C++, including your TestAppDelegate.

Instead, you'd need to do something like this to completely hide the C++ within the CppWrapper.mm file:

//  CppWrapper.h
#import <Foundation/Foundation.h>

@interface CppWrapper : NSObject {
    void *myCppClass;
}
- (void)doSomethingWithCppClass;
@end


//  CppWrapper.mm
#import "CppWrapper.h"
#import "CppClass.h"

@implementation CppWrapper

- (id)init {
    self = [super init];
    if (self) {
        myCppClass = new CppClass;
    }    
    return self;
}

- (void)dealloc {
    delete myCppClass;
    [super dealloc];
}

- (void)doSomethingWithCppClass {
   static_cast<CppClass *>(myCppClass)->DoSomething();
}

@end
like image 123
NSGod Avatar answered Oct 24 '22 06:10

NSGod