Making a Objective-C Wrapper for a C++ Library
I am trying to make a wrapper in Objective-C so I don't have to write c++ outside the library classes.
The Library main file is LLAHProc开发者_JAVA技巧essor.h .cpp
My Wrapper is LLAHProcessorWrapper.h .mm
It compiles fine, but when I add LLAHProcessorWrapper
to other class, (Lets say an UIView) as a member variable I get hundreds of errors, like:
#include <map> : Map no such a file or directory
and in every c++ class/struct:
Expected specifier-qualifier list before ClassName
Is like compiler is not recognizing c++ code.
I wonder what am I missing here. Does it has to be something with the fact I added this to Xcode Target Properties: ?
Other Link Flags : -lstdc++ -lz
Or maybe I need to add new flags here?
Thanks in advance
Your problem is that .m
files are compiled as C instead of C++. Thus when the compiler comes across any C++ even in a header file while compiling a .m
file, it will barf.
No doubt you have to put some C++ in your header file because your Objective C object wraps a C++ object, but there are ways around this. One way would be to use a pointer to the C++ object and make use of the handy preprocessor define __cplusplus
which is defined for C++ (and Objective-C++) but not for C (or Objective-C) e.g.
// LLAHProcessorWrapper.h
#if defined __cplusplus
class MyCPPClass; // forward class declaration
#else
typedef struct MyCPPClass MyCPPClass; // forward struct declaration
#endif
@interface MyOCClass : NSObject
{
@private
MyCPPClass* cppObject;
}
// methods and properties
@end
Since you never dereference the members of the cppObject outside of the .mm
file it doesn't matter that you never provide a full definition for the struct.
You would new
and delete
the pointer in -init
and -dealloc
respectively. You would include the full C++ class declaration in LLAHProcessorWrapper.mm
.
All you need to do is to create a .mm
as you have done, and the compiler should take care of everything.
The caveat being that it is not safe to have anything C++ related in the .h
files, since they can/will be imported by other Objective-C only files, and then everything breaks down. The main problem here is that you can not define C++ types directly as instance variables for your Objective-C wrapper class, unless every single .m
file is renamed as a Objective-C++ .mm
file.
The solution is to define the instance variables as void*
in the header file, and access them with type casting from the implementation file. Easiest solution for this would be to access the instance variable using a private property that to the typecast for you.
Example code assuming Foo
is a C++ class defined in Foo.h
:
// FooWrapper.h
#import <Foundation/Foundation.h>
@interface FooWrapper : NSObject {
@private
void* foo;
}
// Actual wrapper API for Foo…
@end
// FooWrapper.mm
#import "FooWrapper.h"
#include <map>
#include "Foo.h"
@interface FooWrapper ()
@property(nonatomic, assign) Foo* foo;
@end
@implementation FooWrapper
-(Foo*)foo {
return (Foo*)foo;
}
-(void)setFoo:(Foo*)aFoo {
foo = (void*)aFoo;
}
// Implementation of actual API for Foo…
@end
In any header (.h
) file in which you want to refer to LLAHProcessorWrapper
, use forward class definitions instead of imports, like so:
@class LLAHProcessorWrapper;
@interface SomeView : UIView {
LLAHProcessorWrapper *wrapper;
}
and make sure that the corresponding implementation file has #include LLAHProcessorWrapper.h
or #import LLAHProcessorWrapper.h
.
Any implementation file in which you #include
or #import
your header must have .mm
as its suffix if LLAHProcessorWrapper.h
or anything else in the entire include tree has any C++ syntax at all. In this way, having one .mm
file has a tendency to mean that huge portions of a codebase must have their files renamed to .mm
.
精彩评论