C/C++ Guides

Home

Extending HTML5 Mobile Apps with C++

With the MoSync SDK you are not restricted to just coding in HTML5/JavaScript. You can use the Wormhole communication bridge to talk to C/C++ from JavaScript — really useful when you want to extend your HTML5/JavaScript application with custom code written in C++.

If you are not familiar with how to create an HTML5 project, please read the tutorial Developing Apps in HTML5/JavaScript.

Invoke C++ Code from JavaScript

The following example code is based on the HTML5/JS/C++ Hybrid Project Template. This template illustrates how to invoke custom C++ code from JavaScript. The UI has buttons for making the device vibrate and beep.

To create a project based on this template, launch MoSync SDK, and create an app in the Eclipse-based IDE, using the HTML5/JS/C++ Hybrid Project template. Then you will get the source code discussed below.

The template app uses the Wormhole C++ library (classes HybridMoblet and MessageStream) and the JavaScript libraries included in the file wormhole.js (all included with the application template).

Sending String Messages

It is good to know that two message formats are supported by Wormhole: JSON messages and String stream messages. The example we discuss here uses String streams.

String streams are a performant way of sending messages from JavaScript to C++. This method is generally faster than JSON messages (on some platforms 20x faster). Parsing on the C++ side is very efficient, and streams of string messages are concatenated before passed to C++. This makes sending a large number of small messages efficient.

The JavaScript function mosync.bridge.send() is used to send string messages to C++:

mosync.bridge.send(messageArray, callbackFunction)

This function takes two parameters. The first parameter "messageArray" is an array of strings.These values will be sent to C++. By convention, the protocol for sending custom messages is based on the first element in the array being the string "Custom", and the second element being the name ("action") of the message, like "Beep". Then follows any parameters. (See example below.)

The second parameter "callbackFunction" is an optional function that you can use to send back a result value from C++ to JavaScript. The communication mechanism is asynchronous, which is why a callback function is used to pass the result back from C++ to JavaScript.

Here is an example of a JavaScript call that sends a custom message C++ to make the device vibrate (here we do not need to use any callback function):

mosync.bridge.send(["Custom", "Vibrate", "500"]);

This JavaScript code is found in file index.html in the generated template application.

In the corresponding implementation in C++, the message "Vibrate" is first registered in the constructor of the the application's Moblet, in class MyMoblet. A Moblet is the main object in a MoSync application, and the constructor is a good place to declare message to method bindings.

The addMessage method binds the message name to a C++ method:

addMessageFun(
    "Vibrate",
    (FunTable::MessageHandlerFun)&MyMoblet::vibrate);

This C++ code is found in file main.cpp in the generated template application.

Here is the C++ code for the vibrate method:

void vibrate(Wormhole::MessageStream& message)
{
    int duration = MAUtil::stringToInteger(message.getNext());
    maVibrate(duration);
}

The call to message.getNext() retrives a char pointer (char*) to the next parameter in the message stream, in this case the duration time ("500"). If there are no more messages, NULL is returned.

Note that when a message handling method is called, the first two elements of the original string array sent from JavaScript have been "consumed" by the message handling framework, and the first call to message.getNext() will therefore return a pointer to the first parameter in our message, the value "500".

You can also have messages with no parameters. The "Beep" message is an example of this. Here is the call made from JavaScript:

mosync.bridge.send(["Custom", "Beep"]);

The message handler is registered like this in C++:

addMessageFun(
    "Beep",
    (FunTable::MessageHandlerFun)&MyMoblet::beep);

And here is the C++ code for the beep method:

void beep(Wormhole::MessageStream& message)
{
    maSoundPlay(BEEP_WAV, 0, maGetDataSize(BEEP_WAV));
}

Next, we will take alook at how to return values from C++ to JavaScript.

How to Call JavaScript Code from C++

Note that the code below is not part of the code you get with the template application. You can however type it in yourself, to further explore how the code works.

To evaluate JavaScript code in the WebView from C++, you can use the HybridMoblet::callJS() method. Here is an example:

callJS("alert('Hello World')");

The following snippets illustrate how to invoke C++ from JavaScript and call a JavaScript callback function.

Here is the JavaScript part:

mosync.bridge.send(
    ["Custom", "GetScreenSize"], 
    function(width, height) {
        alert("Screen size: " + width + ", " + height);
    });

And here is the C++ part. First register the message handler in the MyMoblet constructor:

addMessageFun(
    "GetScreenSize",
    (FunTable::MessageHandlerFun)&MyMoblet::getScreenSize);

Then define the getScreenSize method. Here we create a script that invokes the JavaScript function mosync.bridge.reply() with the callbackId of the message and the result parameters (this will call the function specified above, in the call to mosync.bridge.send):

void getScreenSize()
{
    const char* callbackId = message.getNext();
    char script[512];
    sprintf(
        script,
        "mosync.bridge.reply(%d, %d, %d)",
        callbackId,
        EXTENT_X(maGetScrSize()),
        EXTENT_Y(maGetScrSize()));
    callJS(script);
}

The JavaScript function mosync.bridge.reply() always takes the callbackId as the first argument. You can then supply a variable number of arguments (zero to many) that will be passed to the callback function in JavaScript.

Under The Hood

If you wish to dig deeper, you can explore the MoSync source code at GitHub, and you can also take a look at the example program WebViewGeoLocation, which is a low-level example that does not use the Wormhole library. Note that wormhole.js is a generated file, made up of several JavaScript source files (which means it is not found in the GitHub repository).

Items of interest:

  • The source code of the Wormhole library at GitHub.
  • The JavaScript files that make up wormhole.js are found in jslib
  • The class HybridMoblet is the basic building block in a MoSync HTML5 application
  • Classes MessageStream and MessageHandler handles messages from JavaScript
  • The JavaScript NativeUI and PhoneGap implementations are found in Libs

Documentation:

 

 

MoSync SDK 3.3
Copyright © 2013 MoSync AB
www.mosync.com