Reputation: 5666
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
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
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
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
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