Mixing C++ and Objective-C - c++

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?

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

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.

Related

How to pass a callback function from C++ to Objective-C

I don't want to use NSNotification because it is so messing up internally. Is it a way to pass a callback function from C++ to Objective-C++, and let Objective-C call it?
The problem is that I don't know how to pass a function written in C++ to Objective-C++, and how could I use that callback in Objective-C++? Is it a pointer?
I know I can mix them up but my class has to be a C++ class because it inherits some C++ classes.
You're not 100% specific as to the exact use case you're trying to cover here, but I'm going to set out a scenario where this kind of situation occurs, and then show you how to solve it. I hope that will cover your problem too.
So I'm going to assume you have an Objective-C class MyClass with its interface declared in MyClass.h:
#interface MyClass : NSObject
- (void)someMethod;
- (void)otherMethodWhichShouldTakeACallback:?????;
#end
You now have a C++ class MyCPPClass, declared in MyCPPClass.hpp on which you want to pass memberFunction as the callback argument to the otherMethod on MyClass:
class MyCPPClass : public MyBase
{
void memberFunction();
};
First, we need to figure out the method signature on MyClass. The modern way for callbacks in Objective-C is with Blocks. Blocks work pretty well with Objective-C++, so let's go with that and modify MyClass.h with the following line:
- (void)otherMethodWithBlock:(void(^)(void))callbackBlock;
The calling code will need to reside in an Objective-C++ compilation unit (caller.mm):
void callOtherMemberWithCPP(MyCPPClass* cpp_obj, MyClass* objc_obj)
{
[objc_obj otherMethodWithBlock:^{
cpp_obj->memberFunction();
}];
}
Note that this does not deal with object lifetimes. If you're managing lifetimes on the C++ side with std::shared_ptr, you can use that in your Objective-C++ code too, in which case we might end up with something like:
void callOtherMemberWithCPP(std::shared_ptr<MyCPPClass> cpp_obj, MyClass* objc_obj)
{
[objc_obj otherMethodWithBlock:^{
cpp_obj->memberFunction();
}];
}
In this case, the C++ object will only have its reference count decremented when the Objective-C class is done with the block.
For completeness, the other way to do this would be to use C function pointer syntax. In this case, you would need to declare the Objective-C method along these lines:
- (void)otherMethodWithCallback:(void(*)(void*))callback object:(void*)opaqueCallbackArgument;
And the C++ class's method call would need to be wrapped in a free function or static member function:
void memberFunctionCallback(void* opaque_object)
{
MyCPPClass* object = static_cast<MyCPPClass*>(opaque_object);
object->memberFunction
}
…and then call the Objective-C method like this:
[objc_obj otherMethodWithCallback:memberFunctionCallback object:cpp_obj];
Making this version work nicely with automatic lifetime mechanisms such as shared_ptr is a lot more tricky though.

Have C++ class manage life of Objective-C class?

Here is what I am not sure about:
I have a c++ class that will create and own an obj-C object and very simply, when that C++ class is constructed I call:
this->objCObject = [ThatObject new];
But how do I deal with destroying the ObjC object in ~MyCPPClass() ? Under ARC there is no retain/release.
Thanks
You could disable ARC for the specific file that contains your CPP class. That will give you the freedom to use retain/release in your CPP class.
If you have multiple cases that need the same trick, you could look at the shared_ptr for Objective-C objects

Objective-C++: Headers and Class Methods

I've been learning Objective-C for the last few months with the goal of writing iOS games. I want to be able to make the games relatively easy to port to other platforms, so I've also been simultaneously learning C++. My plan is to write most of the game in C++ and write the drawing and game loop in Objective-C. I know (at least I've been told) this is possible, but there are a few things that I'm still confused about.
I'm still pretty new to C++, and coming originally from Java, is it a bad idea to have functions return type be void?
Is there a way to write class functions? ie. className.function(); rather than object.function();
I've never needed header files for my C++ files before. Could someone point me in the direction of an example? Preferably one that has a constructor method? I don't know what to make its return type. (It should be a pointer to the class right?)
I'm going to assume your questions are about how to write C++, as that seems to be what you're asking.
Not at all, void functions are well-accepted in nearly all languages, C++ and Objective-C included. (Though many people prefer returning a bool success/fail value)
You're probably looking for static functions. These don't require instantiation, but there are some limits on their use (see here for more info).
Any non-trivial C++ project should use header files. They serve several purposes, including keeping your code more organized and modular, decreasing compile-time in many cases, and aiding in conceptualizing your design before you think about implementation.
An important thing to note when breaking your class into .h and .cpp files is the use of the scope modifier :: when defining functions. When defining the function public void foo() in your .cpp file, after having declared it in your header, you must use public void ClassName::foo() { }. This is because you defined foo while in the class ClassName { } block in your header, but you are now in the global scope.
(As for your question about C++ constructors, if should be public ClassName::ClassName(); and you don't need to return anything).
Now obviously, many of these points differ in Objective-C. For example, the init method (comparable to the C++ constructor) does, as you said, return a pointer to the object being inited. If you want specific information on writing cross-language apps, you should update your question to be more specific, or open a new question.
No that is fine.
Yes: Assume SomeClass.h:
#pragma once
class SomeClass {
public:
static bool myStaticMethod();
};
and in SomeClass.cpp:
#include "SomeClass.h"
bool SomeClass::myStaticMethod() {
// A static method
return true;
}
See the first part of 2, above.
Some other notes:
A. Change all your Objective-C interface code to Objective-C++ by renaming all the .m files to .mm. This way you can use your C++ code freely.
B. I couldn't think of a B.

Calling an Objective-C class method from C++

I am having some trouble calling an objective-c class method from a C++ file. Example:
In my .h:
#interface MyClass : NSObject {
}
+ (void)myMethod:(NSString *)str;
In my .m:
+ (void) myMethod:(NSString *)str { ... }
In my .cpp:
??
How can you call myMethod since there is no class instance? Its essentially a static?
Thanks
Objects in C++ are incompatible with objects in Objective-C. You cannot simply call an Objective-C method from C++.
There are some solutions, however:
Use Objective-C++. Rename your .cpp to .mm, then you can use Objective-C syntax in your C++ code: [FlurryAnalytics myMethod: #"foo"];
Use direct calls to the Objective-C runtime system. I won't tell you how to, because I really think you shouldn't, and in fact that you don't want to.
Write a plain-C interface. That is, in some .m file, define void myFunction(const char *str) { ... } and call that from C++. You can find an example of this here.
You're going to need a .mm to call an Objective-C method, rather than a .cpp. Beyond that your comment that 'it's essentially static' is accurate in the sense that you would call it with similar logic to the way you would call static class functions in C++:
[MyClass myMethod:#"Some String"];
Though the method isn't static in the C++ sense for a bunch of reasons that don't affect this answer — it isn't resolved at compile time and it does operate within a class (the MyClass metaclass).

C opaque pointer gotchas

I'm working with a legacy C library interface (to C++) that exposes opaque pointers as
typedef void * OpaqueObject
In the library:
OpaqueObject CreateObject()
{
return new OurCppLibrary::Object();
}
This of course provides absolutely no type safety for clients of this library. Should changing the typedef from a void pointer to structure pointer work exactly the same, but provide a small amount type safety?
typedef struct OpaqueObjectInternal_ *OpaqueObject
// OpaqueObjectInternal_ is NEVER defined anywhere in client or library code
Are there any alignment issues or other gotchas that I have to worry about now that I am explicitly pointing to a structure, even though I'm really not pointing to one?
There are no gotcha's; that form is preferred exactly because of type safety.
No, alignment is not an issue here. The pointer itself has a known alignment, and the alignment of the object it will point at is only of concern to the library implementation, not the user.
Actually, a C++ class is also a C struct. So you could simply do this:
struct Object;
struct Object* Object_Create(void);
And, the C wrapper in the library thus:
struct Object* Object_Create(void)
{
return new Object;
}
A method call might look like this:
uint32_t Object_DoSomething( struct Object* me, char * text )
{
return me->DoSomething( text );
}
I have tried this and I see no downsides.
The first thing to consider with your suggested course is what are you communicating to the others that may have to maintain the code you are writing. Above all other things opaque objects are the C way to indicate to the user of a library that the library maintainer makes absolutely no guarantee as to the implementation of an object other than that the object can be used with the documented functions. By removing the void* you are basically announcing to the world, "I declare this implementation that was once opaque to be stable." This may not be what you want.
Secondly, IMHO you are proposing is the sort of half solution that makes no one happy, a better approach is to develop a wrapper class. This has the added benefit of allowing you to wrap the init and destroy functions that inevitably accompany C style opaque objects in the constructors and destructor of you class. This will allow you to provide resource management as well as type safety to your clients with out a whole lot more work.