Question

Ok, first, I must admit that this is my first experience with C++. With that cleared, I would like to proceed. The question is as simple as that, but with some (weird) twist. I am trying to wrap a C++ library into Objective-C code. Suppose the C++ class named "my_class" has a has a method "get_string", which returns another class "my_second_class" which has a method named "my_string", which returns an std::string and I want to put it into a property NSString named "MyNSString" for my Obj-C Class "MyClass".

Here's the code. I've skipped the includes/imports and the 'using namespace' parts. They exist.

MyClass.h

@interface Torrent : NSObject {
    my_class myCls;

@property NSString *MyNSString;

- (instancetype)initWithHandle:(void*)handle;
- (void)setInfo;

@end

MyClass.m

@implementation MyClass

@synthesize MyNSString;

- (instancetype)initWithHandle:(void*)handle {
    self = [super init];
    if (self) {
        myCls = static_cast<my_class*>(handle);
        if (! myCls->is_valid()) return nil;
        [self setInfo];
    }
    return self;
}

I have not implemented setInfo. That is where the errors start. So, I will go through each of my attempts which are specific to the question.

Attempt #1

- (void)setInfo {
    my_second_class mySecCls = myCls->get_string();
    MyNSString = @(mySecCls.my_string().c_str());
}

Attempt #2

- (void)setInfo {
    MyNSString = @(myCls->get_string().my_string().c_str());
}

Attempt #3

- (void)setInfo {
    my_second_class mySecCls = myCls->get_string();
    NSString *unusedString = @(mySecCls.my_string().c_str());
}

Attempt #1 fails, #2 and #3 succeed. I also must mention that there are ~75 such values which need to be updated every one second(I use NSTimer in code), so attempt #2 is a hit on performance. #3 is clearly useless, but somehow, it works. I want to know why #1 fails, while #3 and #2 succeed.

I would also appreciate it if somebody could give me the link to some modest(not too big, nor too small) Objective-C++ code.

EDIT: Attempt #1 causes EXC_BAD_ACCESS code=1

Thanks.

Was it helpful?

Solution

Here's my guess, as we're currently missing some relevant information.
Does your get_string() method maybe return a (possibly const) reference to a my_second_class instance ?
If that is the case, then the first attempt fails because mySecCls is a local object that gets destroyed when the function returns. After that destruction happens, MyNSString points to some invalid memory location on the stack. The second attempt works because no such local (i.e. temporary, from the point of view of your class) object gets created, and the pointer passed points to the contents of the more durable myCls object.

(I also assume that my_string() returns a const std::string& and not a string, or you'd get the same kind of issue with the resulting temporary variable).

If you want to make something that works like attempt #2, but looks a bit more like attempt #1, you can try:

- (void)setInfo {
    const my_second_class& mySecCls = myCls->get_string();
    MyNSString = @(mySecCls.my_string().c_str());
}

However, this is pretty much equivalent to attempt #1.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top