Question

I am using a small C++ library in a Cocoa application (atm just a very simple example to learn how I should do it).

So I have a small C++ class in a namespace looking like follows:

namespace testlib {
class Test {
public:
    Test(unsigned a);
    Test operator+(const Test& other) const;
    Test operator+(unsigned other) const;
    Test& operator+=(unsigned other);
    Test& operator+=(const Test& other);
    unsigned getValue() const;
private:
    unsigned theValue;
};
}

Then I have an .h file with the follwoing code:

#import <Foundation/Foundation.h>
#import "testlib.h"

@interface test : NSObject {
     testlib::Test* testClass;
}

- (id)init;
- (id)add: (unsigned)value;
- (unsigned)value;
- (void)dealloc;

@property void* testClass;

@end

and finally an implementation (in a file called test.mm):

#import "test.h"

@implementation test

@synthesize testClass;

- (id)init {
 testClass = new testlib::Test(0);
 return self;
}

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

- (id)add: (unsigned)value {
 *testClass += value;
 return self;
}

- (unsigned)value {
     return testClass->getValue();
}

When I try to compile this, I get the follwing errors:

CompileC build/testipod.build/Debug-iphonesimulator/testipod.build/Objects-normal/i386/WindowController.o WindowController.m normal i386 objective-c com.apple.compilers.gcc.4_2
 cd /Users/sausalito/eth/testipod
 setenv LANG en_US.US-ASCII
 setenv PATH "/Developer/Platforms/iPhoneSimulator.platform/Developer/usr/bin:/Developer/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin"
/Developer/Platforms/iPhoneSimulator.platform/Developer/usr/bin/gcc-4.2 -x objective-c -arch i386 -fmessage-length=0 -pipe -std=c99 -Wno-trigraphs -fpascal-strings -fasm-blocks -O0 -Wreturn-type -Wunused-variable -D__IPHONE_OS_VERSION_MIN_REQUIRED=30000 -isysroot /Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator3.1.3.sdk -fvisibility=hidden -mmacosx-version-min=10.5 -gdwarf-2 -iquote /Users/sausalito/eth/testipod/build/testipod.build/Debug-iphonesimulator/testipod.build/testipod-generated-files.hmap -I/Users/sausalito/eth/testipod/build/testipod.build/Debug-iphonesimulator/testipod.build/testipod-own-target-headers.hmap -I/Users/sausalito/eth/testipod/build/testipod.build/Debug-iphonesimulator/testipod.build/testipod-all-target-headers.hmap -iquote /Users/sausalito/eth/testipod/build/testipod.build/Debug-iphonesimulator/testipod.build/testipod-project-headers.hmap -F/Users/sausalito/eth/testipod/build/Debug-iphonesimulator -F/Users/sausalito/eth/testipod/../testlib/build -I/Users/sausalito/eth/testipod/build/Debug-iphonesimulator/include -I/Users/sausalito/eth/testipod/build/testipod.build/Debug-iphonesimulator/testipod.build/DerivedSources/i386 -I/Users/sausalito/eth/testipod/build/testipod.build/Debug-iphonesimulator/testipod.build/DerivedSources -include /var/folders/4f/4fSYMOmtHHSRoBf+XVFQ+k+++TM/-Caches-/com.apple.Xcode.502/SharedPrecompiledHeaders/testipod_Prefix-cwdputxcxpofoydkulngkdplqxbt/testipod_Prefix.pch -c /Users/sausalito/eth/testipod/WindowController.m -o /Users/sausalito/eth/testipod/build/testipod.build/Debug-iphonesimulator/testipod.build/Objects-normal/i386/WindowController.o

 In file included from /Users/sausalito/eth/testipod/Classes/test.h:10,
             from /Users/sausalito/eth/testipod/WindowController.m:10:
/Users/sausalito/eth/testipod/Classes/testlib.h:1: error: expected '=', ',', ';', 'asm' or '__attribute__' before 'testlib'
 In file included from /Users/sausalito/eth/testipod/WindowController.m:10:
/Users/sausalito/eth/testipod/Classes/test.h:13: error: expected specifier-qualifier-list before 'testlib'

/Users/sausalito/eth/testipod/Classes/test.mm:13:0 /Users/sausalito/eth/testipod/Classes/test.mm:13: error: type of property 'testClass' does not match type of ivar 'testClass'

What am I doing wrong?? It looks like it uses a C compiler to compile the header file.

I can wrap this in a Objective-C class when I declare the member as a void* type and then use casting in the implementation. But this is definitely not the most comfortable way of doing it.

Was it helpful?

Solution

Rename your WindowController.m to WindowController.mm.

If the file name is .m, the whole "translational unit" will be compiled in ObjC without the ++. However, in your test.h, you are importing testlib.h which does include C++ code. These C++ code is invalid in C, thus causing the compiler errors.


BTW,

- (id)init {
 testClass = new testlib::Test(0);
 return self;
}

You should call super's init:

- (id)init {
  if ((self = [super init]))
     testClass = new testlib::Test(0);
  return self;
}

The property

@property void* testClass;

should return a Test*.

@property(readonly,assign) testlib::Test* testClass;

OTHER TIPS

If you don't want to rename the file, you can also explicitly tell XCode to compile your ".m" file as ObjC++ by opening the Info window for the file (click on the filename in the left pane of the main XCode window, then hit the blue I "info" button). Change the "file type" to "sourcecode.cpp.objcpp".

For a sample app, I would just rename the file, but if you've got an existing codebase that you don't want to do a wholesale rename on, the "file type" setting can be handy.

go to build settings under the "Compile Source As" change to Objective-c++, and hit build

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top