11

I am using C++ as the app backbone and Objective-C for the GUI, that's fine.

But when it comes to mixing those code together in Objective-C++ (.mm file), I have got a few question:

1. Can I mix STL containers with Objective-C or Cocos2D objects?

E.g. In Objective-C header, can I do the following?

#include <vector>
#include <boost\shared_ptr.hpp>
@interface MyClass : NSObject {
  std::vector<boost::shared_ptr<CCSprite> > m_spriteList;
}

And then in the .mm file, I want to do

CCSprite* newSprite = [/* cocos2d stuff here... */];
m_spriteList.push_back(newSprite);

Is the above code valid? It certainly is in C++, but I am not sure when mixing C++ and Objective-C and Cocos2D.

2. Memory management using C++ smart pointer object in Objective-C?

When I try to use the C++ code in Objective-C, I want to declare a C++ object as a member variable in the Objective-C header file.

Say I have a C++ class declared in the test.h header:

Test{
};

In Objective-C header file, I want to do

#include "test.h"
#incude <boost/scoped_ptr.hpp>

#include <vector>
@interface MyClass : NSObject {
   Test* m_testObjectPtr; // (1)
   boost::scoped_ptr<Test>  m_testOjbSmartPtr; // (2)
}

In the above code, is (2) okay? Can I use smart pointers in Objective-C just like in C++ code? And can I assume the Test class destructor will be called when the MyClass object is destroyed?

Or if (2) is not okay in Objective-C++, is (1) okay? Would I need to manually call delete m_testObjectPtr in dealloc?

CodeSmile
  • 64,284
  • 20
  • 132
  • 217
RoundPi
  • 5,819
  • 7
  • 49
  • 75
  • Separate paths using forward slashes `/` not backslashes `\ `: `#include `. – kennytm Nov 17 '11 at 18:21
  • Yes, thank. And that one got me last week :) Sorry the code above was manually written in stackover without compiler test... – RoundPi Nov 17 '11 at 18:25

2 Answers2

7

You can use smart pointer only on c++ classes. if you use then on objective-c classes you will either get compile error or crash somewhere.
You can also use containers with pointers of objective-c classes like

std::vector<CCSprite *> spriteList;

just make sure you retain them when you insert them to list and release them when you remove them.
In both cases, you can make a smart pointer of your own that calls retain and release in constructor/destruct/copy like needed and then don't worry about retain release.
Also destructor for member c++ objects will be called automatically when the object is deallocated.
An example of an objective c wrapper would be

template<typename T>
struct shared_objc_object
{
    T *Object;
    shared_objc_object : Object(nil) { }
    shared_objc_object(T *Object) : Object([Object retain]) { }
    shared_objc_object(shared_objc_object &other) :
        Object([other.Object retain]) { }
    ~shared_objc_object() { [Object release]; }
    shared_objc_object &operator =(shared_objc_object &other)
    {
        [Object release];
        Object = [other.Object retain];
    }
}

And you can use

std::vector<shared_objc_object<CCSprite *>> spriteList;
spriteList.push_back(some_sprite);

and don't care about retain/release

Daniel
  • 30,896
  • 18
  • 85
  • 139
  • Dani, thanks for the quick reply. What do u mean call retain when insert ? Do u mean something like spriteList.push_back([newSprite retain]); ? – RoundPi Nov 17 '11 at 18:24
  • Dani, can u reply to my comments above about retain ? – RoundPi Nov 17 '11 at 18:41
  • @Gob00st: yes, and `[newSprite release]` whenever you remove it from the vector or the vector destructs. – Daniel Nov 17 '11 at 18:49
4

There are some issues you'll want to be aware of. C++ classes do not enjoy the same scope based lifetime you might be used to when made into class members of Objective-C++ objects. When alloc/initing, the constructor won't be called, and when releasing, the destructor won't be called, unless you carefully use in place new/delete or hold on to a pointer and explicitly manage it with new/delete.

Also, if the Objective-C++ header needs to be shared with Objective-C files, you cannot use any C++ constructs at all. Both problems can be mitigated by hiding all C++ members using the pimpl pattern.

Can I mix STL containers with Objective-C or Cocos2D objects?

Yes, since Objective-C objects are just pointers to structs, you can store them easily in STL containers and even forward declare the type and pass it into pure C++ code. (Note, the C++ code can't really do much with the pointer without tricky and brittle code, but you can always pass the pointer back into Objective-C code later to get useful work done.)

Memory management using C++ smart pointer object in Objective-C?

You can use smart pointers to manage the lifetime of your Objective-C objects, but you will need to be careful that they do not call delete (the default behavior for most C++ smart pointers). With shared_ptr from C++11 or boost, you can provide a custom deleter; though now you have two reference counting systems. You can instead use boost::intrusive_ptr to skip that extra overhead and use Objective-C's reference counting directly.

Marc
  • 408
  • 3
  • 6
  • "now you have two reference counting systems", do you mean one reference counting from objective-c in io5 and another from smart pointer ? Also can u please provide a simple example to explain the usage of boost::intrusive_ptr and obejctive-c pointer ? – RoundPi Nov 18 '11 at 00:10
  • @Gob00st - Yes, both NSObject and shared_ptr implement reference counting, so it is a bit of a waste to use shared_ptr if you can leverage the built in Objective-C reference counting, though it still might be easier than intrusive_ptr. As for intrusive_ptr, I'll try to write up a full example later, but [boost's website](http://www.boost.org/doc/libs/1_48_0/libs/smart_ptr/intrusive_ptr.html) might get you started (though the docs for intrusive_ptr are quite lacking...). – Marc Nov 18 '11 at 02:21