![]() |
CloudBuilder
2.8.4
Making social games is easy !
|
In the CloudBuilder SDK, most of the API calls are configurable through a JSON entity called CHJSON
, which behaves as a dictionary like a JSON object. Here is an example:
To write your CHJSON objects, the following methods are recommended:
void CotCHelpers::CHJSON::Clear()
void CotCHelpers::CHJSON::Delete(const char *aItem)
CHJSON* CotCHelpers::CHJSON::Duplicate() const
const CHJSON* CotCHelpers::CHJSON::Empty()
void CotCHelpers::CHJSON::Put(const char *aKey, bool aValue)
void CotCHelpers::CHJSON::Put(const char *aKey, int aValue)
void CotCHelpers::CHJSON::Put(const char *aKey, double aValue)
void CotCHelpers::CHJSON::Put(const char *aKey, const char *aValue)
void CotCHelpers::CHJSON::Put(const char *aKey, CHJSON *aValue)
void CotCHelpers::CHJSON::Put(const char *aKey, const CHJSON *aValue)
void CotCHelpers::CHJSON::Put(const char *aKey, const CHJSON& aValue)
CHJSON* CotCHelpers::CHJSON::parse(const char *aJsonString)
char* CotCHelpers::CHJSON::print() const
char* CotCHelpers::CHJSON::printFormatted() const;
If performance is less a concern to you or if you want to do quick prototyping, you may as well use CHJSON
objects by reference. In that case, do not forget to delete the object when not needed anymore. Note that when putting an non-const CHJSON
object inside another however, ownership is transferred to the new container, so you do not need to delete it yourself. This enables constructs as shown below.
Arrays should not be needed, but you can create them like this:
CHJSON
objects are also used when returning a value from the SDK. Most of the calls take a callback (CloudBuilder::CResultHandler) which has the following form.
This object is guaranteed never NULL
(at worst it is empty). You can read from CHJSON
objects in a safe and compact way using this recommended set of methods.
bool CotCHelpers::CHJSON::Has(const char *key) const
const CHJSON* CotCHelpers::CHJSON::Get(int aIndex) const
const CHJSON* CotCHelpers::CHJSON::Get(const char *aItem) const
const CHJSON* CotCHelpers::CHJSON::GetSafe(int aIndex) const
const CHJSON* CotCHelpers::CHJSON::GetSafe(const char *aItem) const
double CotCHelpers::CHJSON::GetDouble(const char *aItem, double defaultValue) const
int CotCHelpers::CHJSON::GetInt(const char *aItem, int defaultValue) const
bool CotCHelpers::CHJSON::GetBool(const char *aItem, bool defaultValue) const
const char* CotCHelpers::CHJSON::GetString(const char *key, const char *defaultValue) const
Iterator CotCHelpers::CHJSON::begin() const
Iterator CotCHelpers::CHJSON::end() const
int CotCHelpers::CHJSON::size() const
If you expect to have an object such as {"obj": {"value": 123}} then you can safely do the following.
It will work because all Get*
methods (except CotCHelpers::CHJSON::Get itself which might return NULL
) will safely handle the fact that the desired object does not exist and return a default value. In the case of CotCHelpers::CHJSON::GetSafe it is simply an empty object (see CotCHelpers::CHJSON::Empty) so you may transitively query for additional keys within the hierarchy without worrying.
Optionally, you can also pass a default value to the Get*
methods, which will be returned in case the element is not found.
Listing the sub-nodes ("values") of a CHJSON
can be done easily using the provided iterator.
This can be done for arrays as well, but nodes obviously won't have a name. This snippet is provided here for reference:
The CloudBuilder SDK uses a strongly asynchronous programming model, with callbacks and listeners in many places to process data coming from the network. To achieve that, the model relies on a class named CDelegate
, which basically allows to pass a pointer to a method with a given signature to be executed later when the arguments have become available. For reference, here is a sample of game requiring you to guess a number, with the method to check being passed as argument:
The same principle is used with CResultHandler
, which is actually just a kind of CDelegate
with standard arguments. Usually, you will want to create result handlers by using the provided MakeResultHandler method:
It will create the appropriate type of delegate using genericity, and the Setup method will not accept it if the type differ, meaning that you will have to fix the signature of your OnSetup method to match the expected one.
The MakeResultHandler
allows you to pass additional parameters, which will be forwarded to your method as additional arguments trailing the default ones. An example is shown below.
You can pass up to 3 parameters of any type, even a struct if you like. However, on a performance point of view, keep in mind that the parameters may be copied multiple times around, so it is peferrable to use either small and simple structures or pass a pointer. Also note that if you pass a pointer to something, it has to remain valid until the callback is called, so you will probably want to duplicate the object and delete it inside the callback as shown above with the strdup/free combo.
Using polymorphism, it is also possible to make fully custom callbacks, which just have to respond to the specification of a CDelegate
(that is, basically to provide an object/method combo corresponding to the signature, to be invoked). Anonymous structures come in handy for this task:
The only problem here is that your anonymous structure doesn't have access to the enclosed members. You need to capture them manually, as shown below for the this
pointer.
However, now that you know the inners of these delegates, you can forward the original call anywhere you like. You may for instance forward the call to a C++11 lambda as shown below, enabling for very nice constructs.
If you are using Visual C++ 2010, beware that there is a bug preventing nested lambdas from capturing the same member in this version.