Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ object as an Objective-C++ property

I want to declare a C++ property inside my Objective-C class.

What kind of attributes should I set it to? It seems that strong or retain will lead to an error saying that it is not an object.

How could I manage its memory properly?

like image 904
Patroclus Avatar asked Dec 18 '22 21:12

Patroclus


1 Answers

You are right, the property cannot be weak, strong, or retained; for that it would have to be a pointer to an Objective-C object. If you don't use any attributes on a C++ property, it will default to unsafe_unretained,assign,atomic.

A few other things to consider, assuming the Objective-C(++) object controls the lifetime of the C++ property:

  • Because you can't do much with a C++ object in Objective-C, the
    property is mostly useful in Objective-C++ code, where you can mix
    Objective-C and C++.
  • Because you have to manage the property's memory on your own, you need a custom setter.
  • Because the property defaults to atomic, you need to use synchronization in the setter and need a custom getter, too. You could declare it nonatomic, in which case you would not need to synchronize and would not need a custom getter.
  • You can implement dealloc to ensure the C++ object is freed when the Objective-C++ object goes away.

Here's some useful documentation from Apple: https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/ProgrammingWithObjectiveC/EncapsulatingData/EncapsulatingData.html.

And here is a quick example. Let's say the C++ class you are using for the property is called MyCPP. In a header you could have:

@interface ClassOCPP : NSObject

// This property can only be used in Objective-C++ code
#ifdef __cplusplus
@property /*(unsafe_unretained,assign,atomic)*/ MyCPP * myCPP;
#endif

// Other stuff may be usable in regular Objective-C code.

@end

Implementation could be as follows (in a .mm file; remember, it's Objective-C++):

@implementation ClassOCPP
{
    MyCPP * _myCPP;
}
-(id)init {
    self = [super init];
    _myCPP = NULL;
    return self;
}

-(void)setMyCPP:(MyCPP*)newVal {
    @synchronized(self) {
        delete _myCPP;  // it's OK to delete a NULL pointer
        _myCPP = newVal;
    }
}

-(MyCPP*)myCPP {
    return _myCPP;
}

-(void)dealloc {
    puts("De-allocating ClassOCPP.");
    delete _myCPP;
}

@end
like image 136
Anatoli P Avatar answered Jan 10 '23 07:01

Anatoli P