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:
| (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()); |
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++:
| (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:
| [ "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:
| (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):
| const char * callbackId = message.getNext(); |
| "mosync.bridge.reply(%d, %d, %d)" , |
| EXTENT_X(maGetScrSize()), |
| EXTENT_Y(maGetScrSize())); |
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.
Comments
Post a Comment