Wrapping C++ – Take 2, Part 1
Last year, I presented an approach to wrapping C++. Since then, I’ve been introduced to other approaches, particularly from gf who helped me better understand opaque objects. Since I do a lot of cross-language work, I’ve had some opportunity to play with and expand this, and so I’d like to update my C++ wrapping approach.
First, to remind everyone of the problem: you have a C++ object that you want to consume in Objective-C. That’s easy in ObjC++, but if you make an ivar that references a C++ class, then the header file can only be included by ObjC++ classes. This quickly spreads .mm files throughout your project, creating all kinds of headaches. ObjC is a beautiful thing, and C++ is fine, but ObjC++ is a crazy land that should be carefully segregated from civilized code. So how do we do it?
We create a thin wrapper object to provide an ObjC face on a C++ object. The challenge is how to hide C++ classes from the header file. The answer is to put them in a struct that you forward declare so you don’t have to expose its contents. Structs are almost identical with C++ classes, but their forward declaration syntax is C-compatible (unlike class). Let’s look at how this is done.
For this example, we will consider a C++ class called RN::Wrap. It holds a simple string with set and get accessors.
class Wrap {
public:
Wrap(string str) : m_string(str) {};
string getString() { return m_string; };
void setString(string str) { m_string = str; };
private:
string m_string;
};
We wrap this into Objective-C++ using an opaque structure, RNWrapOpaque:
struct RNWrapOpaque;
@interface RNWrap : NSObject {
struct RNWrapOpaque *_cpp;
}
Since we only include a raw pointer to RNWrapOpaque, we don’t have to declare anything else about it in the header file. If we tried to store the actual struct here (rather than a pointer), then that would defeat the purpose. This is the only raw pointer we will need.
Since structs are almost identical to classes in C++, we can use class features like constructors and destructors in the implementation (.mm file):
struct RNWrapOpaque {
public:
RNWrapOpaque(string aStr) : wrap(aStr) {};
RN::Wrap wrap;
};
Now initializing and using the opaque object is easy in ObjC++ code:
- (id)initWithString:(NSString *)aString {
self = [super init];
if (self != nil) {
self.cpp = new RNWrapOpaque([aString UTF8String]);
}
return self;
}
- (void)dealloc {
delete _cpp;
_cpp = NULL;
[super dealloc];
}
- (void)setString:(NSString *)aString {
self.cpp->wrap.setString([aString UTF8String]);
}
- (NSString *)string {
return [NSString stringWithUTF8String:
self.cpp->wrap.getString().c_str()];
}
A nice side effect of this usages is that C++ objects are easy to detect through the self.cpp prefix. Memory management is easy since there is only one raw C++ pointer.
Using the class requires no special work. It’s pure ObjC:
RNWrap *wrap = [[[RNWrap alloc] initWithString:@"my string"] autorelease];
NSLog(@"wrap = %@", [wrap string]);
In part two, we’ll discuss how to extend this approach to more complex problems such as smart pointers, listeners/delegates, and bindings.

Thanks for such quick and detailed response!
Good to hear that the opaque solution worked out for you :)
Very helpful. Thank you and gf.
What about wrapping a C++ class that has no namespace, and you want to use the same name in ObjC that is of the C++ class? Also, how would you deal with a C++ class that takes it’s own type as a function parameter?
I would not recommend naming the C++ and ObjC classes the same. This is confusing. If it does not take a namespace, I generally add “Wrapper” to the ObjC class. That said, ObjC and C++ classes live in separate namespaces, and so there is no compiler problem with having them be the same. It’s just confusing to read.
I don’t see why there would be any special problem with passing an object to other instances of itself. What problem are you encountering?
Heyas, i am a ObjC novice and a total C++ noob. I just want to have one C++ class (providing large integers for crytography) wrapped into an ObjC class. I fail miserably in understanding your example because i cant figure out the file structure required. So far, C++ class goes to .mm file, but i am missing where the other codesnippets are being put into? And which file imports which other files. Can you enlighten me, please?
thanks in advance MArc
Holyspambatman!
Sorry, i missed your .zip download. Make them bigger :)
regards /M
@Marc: I take it that means you understand now? Or did you still need a hand?
Heyas,
yeah, thanks. i am now much further: my code compiles, even links. Now i have to grab all those traps like call-by-value/reference in the original code which i have changed while porting c# to c++ and have to jump through a few buring loops like return types from C++ methods. Sadly, i lack the proper terminology and – to be honest – oo-skills to do it one handed, it means a lot to learn for me :D
I will come back if i have some questions :D regards /M
Hm, am i really forced to do it like this:
-(NSString*)toString { string r=self.cpp->biginteger.toString();
NSString ret = (NSString)CFStringCreateWithBytes(kCFAllocatorDefault, (const UInt8*)r.c_str(), r.size(), kCFStringEncodingUTF8,false); return ret; }
(feel free to remove/ignore my questions if you feel they are inappropriate… :)
Thanks
@Marc, no, it’s much simpler than than to convert a std::string to an NSString. (Also, your version leaks ret). The solution is:
Thanks Rob, for that improvment. I was partially aware of the leakage, i am currently not at that point to take care about memory managment issues in this mixed code. I am having trouble with the wrapping of overloaded (in c++) operators and object persistance at the moment, so i think its about time i am starting to take memory managment into consideration… sigh
I have a question. Why is the following sequence used relative to _cpp and cpp: 1._cpp declared as the ivar 2. cpp declared as a property (in the.mm file) 3. _cpp set as the ivar to act as the cpp property 4. then cpp used in the methods.
why not instead just do the following: 1. declare cpp as the ivar 2. cpp declared as a property (in the.mm file) 3. just synthesize cpp 4. then cpp used in the methods.
@-C First, you should not directly access your ivars except in a small number of cases (-init, -dealloc and in accessors). You should use accessors. This saves a great deal of suffering when tracking down memory errors due to incorrectly retained objects. While the C++ object doesn’t require retain, you don’t want to be in the habit of looking at code and guessing.
That’s the key to this style. ivars are always
self.var. If the name of the ivar werecpp, then when you see “cpp = foo” it’s unclear whether that’s an ivar or not. Following good ivar hygiene and naming conventions is what separates crashing Cocoa from working Cocoa.Just a quick note to say thank you! I’ve spent a good bit of time trying to figure all this out – reading lots of pages, stackoverflowquestions, and conflicting advice. But this post (and the accompanying zip file – special thanks for including that) were particularly helpful in my understanding. Hopefully I’ll be able to implement it in my own project!
Hi!
I have no idea how this works, but it worked great for me. Can you recommend me some links to explain what is going on here? I can easily reproduce this behavior now, but I can’t understand it.
Thanks!
@dougalg , is there a particular part that is confusing you? Do you understand the opaque structure? Is the C++ or the ObjC that you’re finding confusing?
It is definitely the opaque structure that confuses me. I understand that we are creating an instance of the class that we want to wrap in the struct declaration of the wrapper, and then referring to that via the cpp pointer, but I don’t really understand the struct part.
To clarify, I really don’t understand the part about forward declaration and content exposition. The rest I can figure out from Google, I think.
@dougalg Ah, yes, the struct is actually a trick. It’s a cross-language homonym :D In C++, you can declare a class as a struct. It just makes the members public rather than private, but other than that, it’s still treated as a class. So you get a C++ class that you can legally declare in a pure-C header.
Here’s another write-up similar to mine that walks through the pattern another way: http://www.philjordan.eu/article/strategies-for-using-c++-in-objective-c-projects.
Thanks, that’s also helpful!
Why not just forward declare the class as a struct? C++ classes and structs are compatible so you can simply do:
in your objective-c++ header instead of having to declare a wrapper for it. C (Objective-c) will think of it as a struct and C++ will think of it as a class.
This can work as long as there are no namespaces. In the code I was dealing with, namespaces were common (as you’ll see in the linked example code). Of course now that you can declare ivars in the @implementation block, much of this technique is not required anymore. I still strongly recommend separating ObjC and C++ with a thin ObjC++ layer, but you no longer need funky wrapper classes for your header file.
@Rob Napier I’m an iOS developer with no C++ knowledge and I’ve recently been pointed to your blog as a great resource for instruction on Objective C++ wrappers. I’m wondering if it wouldn’t be too much trouble for you to provide a simple example of what you meant when you said “..now that you can declare ivars in the @implementation block, much of this technique is not required anymore” in response to @mydogisbox’s question: “Why not just forward declare the class as a struct? C++ classes and structs are compatible..” As my c++ header has no namespace, I feel that this would be useful to me and others. Thanks for the help if you had the time. Great blog!
@Orpheus Check out my new post: http://robnapier.net/blog/wrapping-cppfinal-edition-759.