8

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

zpasternack
  • 17,838
  • 2
  • 63
  • 81

2 Answers2

13

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
NSGod
  • 22,699
  • 3
  • 58
  • 66
0

Personally, I would

#include "CppClass.h"

instead of importing it.

That's probably not your problem though.

Rhythmic Fistman
  • 34,352
  • 5
  • 87
  • 159
  • I'm glad you mentioned this, because I was wondering which was more appropriate for bringing a C++ header file into an Objective-C header file. Doesn't solve the problem, though. – zpasternack May 21 '11 at 19:54
  • import simply automates the include #ifndef __CPP_CLASS_H__ dance, so it seems a shame to let those ifndefs go to waste. – Rhythmic Fistman May 21 '11 at 20:47