NDK in cocos2dx is a problem, just because the native features and libraries that we can use on Android(Java) and iOS(Objective-C) are not directly usable
with development under C*+ environment. Most developers who are great at working with cocos2dx on C*+ would face the problem of transferring and
initiating processes or messages on other languages. I have been through that pain too hence i learned the basics of NDK (Native Development Kit) and
how C*+ will communicate with the native languages on different mobile platform .
h2. A reason to use it.
Initially when i was making a game i had a problem of connecting Flurry with the same game on Android and on iOS. It was a pain because i had to write
many #if s for target platforms. More over i wasn’t able to directly communicate things i need to make methods Java and Obj-C as well as different methods
and libraries on C*+ to be able to transfer my data structure and message to the other side of development. Well i took the wrong path then and been in
mess, but from that mess i learned how i can work with C*+ and Obj-C combination as well as C*+ and Java.
I noticed that for working in different languages and with any sort of data structures, String is the only key. String is common in almost any language, with
a char* from C*+ you can communicate with a helper to Java as well as Objective-C. You just need a data definition language that can take your structure
and messages from one end to another. I realised that XML is a good language that can support any of my data structures as well as its definition, but the
problem was for a small amount of message and data structure it would require loads of work as well as a long string which means that transfer time
would be effected as well as memory. I needed a much more sophisticated and a simpler solution to implement as well as define and use the structure.
The first thing that got in my mind was JSON. JSON is almost 1/3rd of XML but has the ability to define any sort of complex structures that xml can define
with its simpler structures. i.e. Dictionary, Array, Integer, Real, Boolean and String. Using these structures i can construct many other structures that i
would require for doing the type of tasks i was planning to do, like Integrating Flurry might just need an API key which means it can be simply sent to the
other side of C*+ with String structure in JSON.
How it works ?¶
I believed this approach will work smoothly and will have a small size of overhead on languages. The problem was to write a JSON parser that could parse a
string to JSON or create a string from any object. Now this any object could have been a hurdle. I can’t allow any object to be passed and fetched on the
other hand. Interestingly working on all three languages i found out that there are common structures we can work on and with a little bit of compromises
can achieve the goal. Like there are CCDictionary and CCArray supported in C**, NSDictionary and NSArray in Obj-C and JSONObjects library in Java. These
three structures behaves mostly the same all can carry JSON Objects with particular types, that can easily be convertible to C** and vice versa.
For this approach to work we need a parser on C*+ side that will convert JSON string to some type and from some type to JSON string, i selected that type
to be CCDictionary or CCArray. So basically we need a JSON object to CCObject parser and vice versa, and a mechanism to call functions on Java and Obj-C
and another mechanism to call back to C**.
h2. Core mechanism.
I used a String to JSON parser named Jansson , which is freely available under MIT license. It turns a char* or a
std::string object to json_t* which is a descriptor object for JSON representation under C**. Over that i wrote a parser for json_t* to CCObject*
and an other parser which parses back from CCObject* to json_t* so that the communication can be smooth. The output and input from and to
C*+ is a string object with json in it.
Model of work¶
From C*+ :¶
If we want to receive messages from other languages to C**, we need to register some selectors to be called on message receive. I named them
selector group. I have exposed a library that will do it for you. It will simply take in arguments as Group Name, Selector String,
Cocos2dx Selector Object and a Receiver. When C*+ receives a message from other language, it simply search for the
Selector String we registered initially or during the run from our scene or any other CCNode. If it finds any string that is compared to the message
received, it simply creates a CCAction that is a CCFiniteTimeAction and in that it creates the selector with CCCallFuncND::create and passed the
data associated with the json (if any) to the receiver that is implementing that selector.
Sending from C*+ is really easy, i have exposed a method name SendMessageWithParams, which has 2 parameters, first is the message name
that will respond to the other side of C*+ that is Obj-C and Java, and a CCObject that can either be CCArray or CCDictionary, which will be passed
to the other languages as parameters to the function name that would be the message name.
From Obj-C and Java :¶
Firstly you will need to assign a receiver object that will respond to message from C**. The only requirement for the receiver is to implement the
methods which are passed from C**, meaning for instance,
If you call this message from C*+
then you must implement other part with a function that would be implemented with a definition of :
* Java :
void SomeFunnyMessage; // Java
* Objective-C :
- SomeFunnyMessage: // Objective-C </pre>
So basically, when you pass a message with a name from C*+ it has a corresponding method on the other hand with receiver. Similarly when you
send a message from other hand, C++ end must have a selector registered to respond to the message.
Where to get it ?¶
I have uploaded the whole source with sample projects on github. It has a very simple example of message passing from Android and iOS. Given below is the link to get it.
Room for improvement¶
I have written this library from my knowledge and previous experiences, if you feel it can be made better or i am doing any mistakes, please feel free to
comment and let me know about it. I will try and work on it as soon as possible to make it a better product that can bring a change in the lives of many.