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

2

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

Patriapatriarch answered 21/5, 2011 at 18:50 Comment(7)
Did you try to restart Xcode 4? When I got the same error, I could resolve by just restarting Xcode 4.Dado
Does this help? https://mcmap.net/q/451605/-xcode-objective-c-avoid-making-hh-files/240633Factitive
@Jinhyung yeah, I tried restart Xcode, also did a Clean; still get the same error.Patriapatriarch
I compiled your code with GCC 4.2 compiler (in xcode 3.2.5) it worked fine.Intermarriage
@ergosys: interesting suggestions, but no, that doesn't help.Patriapatriarch
@Atul: yes, Xcode 3.2.6 with GCC works for me as well. For various reasons, I need to use llvm for this project. Perhaps it's an llvm issue (or setting).Patriapatriarch
I had the same issue including c++ std libs in my AppDelegate class. Turns out I had to also convert main.m into main.mm and then it compiled without error.Fawnfawna
M
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
Metabolism answered 21/5, 2011 at 21:28 Comment(0)
B
0

Personally, I would

#include "CppClass.h"

instead of importing it.

That's probably not your problem though.

Baresark answered 21/5, 2011 at 19:22 Comment(2)
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.Patriapatriarch
import simply automates the include #ifndef CPP_CLASS_H dance, so it seems a shame to let those ifndefs go to waste.Baresark

© 2022 - 2024 — McMap. All rights reserved.