rano
rano

Reputation: 5666

How to wrap a C++ lib in objective-C?

I have a C++ library (.h only) that contains the implementation of a data structure and I'd like to use it in my iPhone app.

Firstly, I wrote a wrapper in objective-C++ as a class that, through composition, has an ivar of the C++ class. I then was 'obliged' to change the wrapper class extension to .mm, and it seemed fine. But then I have to include this wrapped class file into several other files, so I have to change their extension too (in order to prevent a wave of compile-time errors).

Am I correct? Is there a way to 'confine' the .mm extension to just few files?(and so preventing name clashes etc)

EDIT: Some more info that might help, I'm using LLVM 1.5 as the compiler (I noticed that the number of compile time errors varies from GCC 4.2 to LLVM 1.5 but I'm not sure that it means much, since I didn't have a look at them all)

Upvotes: 4

Views: 3348

Answers (4)

sb.
sb.

Reputation: 1150

My preferred solution is this forward declaration macro:

#define FORWARD(cpp_class) struct cpp_class; typedef struct cpp_class cpp_class;

FORWARD(SomeCppClass);

@interface MyObjcWrapper : NSObject {
    SomeCppClass *ptr;
}

Then MyObjcWrapper.h is safe to include in Objective-C and Objective-C++ files.

This is from a helpful blog post I saw a couple years back -- can't seem to find it now.

Upvotes: 1

Barry Wark
Barry Wark

Reputation: 107754

My recommendation is to wrap the C++ bits in #ifdefs:

//MyWrapper.h

#ifdef __cplusplus
class ComposedClass;
#endif 

@interface MyWrapper : NSObject
{
#ifdef __cplusplus
ComposedClass *ptr;
#endif
}

// wrapped methods here...
@end

This is a slightly lame version of the PIMPL idiom, but less code, and effective for hiding C++-isms from your pure Objective-C code. Obvioulsy you would have to include the ComposedClass's header in your MyWrapper.mm.

If ComposedClass is a templated type, you will need to modify the first block to

#ifdef __cplusplus
#include "ComposedClass.h"
#endif

instead of using a forward declaration and then, of course, use the templated type in your Objective-C class' instance variable declaration.

This approach was suggested by Greg Parker, the runtime guru at Apple.

Upvotes: 4

Omnifarious
Omnifarious

Reputation: 56038

I'm not sure I understand your question fully, but I think the answer is 'Yes'.

Basically anything that needs to refer to the wrapper class is Objective-C++ code, not straight C++.

I suggest that you confine your inclusion of the wrapper class to implementation (aka .cpp or the Objective-C++ equivalent) files. They should not cause the header file describing the classes they implement to become Objective-C++.

Techniques like the Pimpl idiom can help isolate users of your class from the fact that it's implemented partly in Objective-C++.

Upvotes: 2

Ole Begemann
Ole Begemann

Reputation: 135550

Any code that includes a C++ snippet (no matter how small) must be compiled with Objective-C++ (and hence be in a .mm file). If you want to narrow down the number of .mm files, you would have to wrap the functionality of your C++ code in an Objective-C class so that this class's public interface (its .h file) only consists of Objective-C code. That means the wrapper class must not contain a public ivar of a C++ type. Whether this is a feasible approach if your C++ lib only consists of a data structure, I don't know.

Note that AFAIK LLVM 1.5 does not include C++ support yet (only LLVM 2.0 does). AFAIK, when you select LLVM 1.5, Xcode will automatically switch to GCC for all C++/Objective-C++ files.

Upvotes: 4

Related Questions