views:

816

answers:

3

I have a lot of shared C++ code that I'd like to use in my iPhone app. I added the .cpp and .h files to my Xcode project and used the classes in my Objective-C++ code. The project compiles fine with 0 errors or warnings.

However, when I run it in the simulator I get the following error when I attempt to access an STL method in my objective-c code (such as .c_str()):

Program received signal:  “EXC_BAD_ACCESS”.

Unable to disassemble std::string::c_str.

Here's an example of the code that causes the error:

[name setText:[[NSString alloc] initWithCString:myCPlusPlusObject->cppname.c_str()]];

where name is an NSTextField object and cppname is a std::string member of myCPlusPlusObject.

Am I going about this the right way? Is there a better way to use STL-laden C++ classes in Objective-C++? I would like to keep the common C++ files untouched if possible, to avoid having to maintain the code in two places.

Thanks in advance!

+3  A: 

Make sure the string isn't empty before passing it to the initWithCString function.

Also the function you're using has been deprecated, use this one instead.

arul
Thanks for that. I stepped through the code and found I hadn't populated the pointer ... rookie mistake!
Fuzzy Purple Monkey
+1  A: 

I would try this:

if (myCPlusPlusObject)
{
    [name setText:[[NSString alloc] initWithUTF8String:myCPlusPlusObject->cppname.c_str()]];
}
else
{
    [name setText:@"Plop: Bad myCPlusPlusObject"];
}

The NULL pointer is likely your problem as the std::String will always be initialized correctly if it exists, and the c_str() method will return a '\0' terminated string even if the string is empty.

Martin York
+2  A: 

Note also that this line of code:

[name setText:[[NSString alloc] initWithCString:myCPlusPlusObject->cppname.c_str()]];

leaks the created string.

Go back and read the memory management rules at http://developer.apple.com/documentation/Cocoa/Conceptual/MemoryMgmt/Articles/mmRules.html.

The main issue is there you have allocated the string, therefore you have taken ownership of it, and you then never release it. You should do one of the following:

[name setText:[[[NSString alloc] initWithCString:myCPlusPlusObject->cppname.c_str() encoding:NSUTF8StringEncoding] autorelease]];

or

NSString* myCPlusPlusString = [[NSString alloc] initWithCString:myCPlusPlusObject->cppname.c_str() encoding:NSUTF8StringEncoding];
[name setText:myCPlusPlusString];
[myCPlusPlusString release];

or

[name setText:[NSString stringWithCString:myCPlusPlusObject->cppname.c_str() encoding:NSUTF8StringEncoding]];

The latter is the best as far as code simplicity is concerned. The middle one is the best as far as memory usage is concerned, which is frequently an issue on the iPhone.

The first one is likely identical to the last one - I say "likely" because there is no guarentee that stringWithCString returns an autoreleased object. It probably does, but whether it does or not is not your concern, all that matters to you is that you do not take ownership of the string because the method name does not begin with “alloc” or “new” or contains “copy” and so you are not responsible for releaing it.

Peter N Lewis
Nice, thanks for that.
Fuzzy Purple Monkey