top

Hello World in C

This tutorial performs a step by step decomposition of the NaCl "Hello world" demo application in C.

Introduction

This article will discuss the structure of the most basic NaCl application written in the C programming language. The source code can be found in Tizen Studio or you can click here. The downloaded zip file can be imported into Tizen Studio or extracted and compiled using a separately downloaded NaCl toolchain. Build instructions are available in the demo package

Important

Please note that you need at least pepper_42 toolchain version to compile this sample application.

We recommend to go through this tutorial along with analyzing the downloaded source code. This decomposition will only focus on the native part of the NaCl application, the web part (.html and .js code) will be omitted because it’s trivial and almost identical for every demo presented on this website. If you want to learn more about NaCl or how to implement a basic NaCl application from scratch, read Nacle Getting Started and How to Create a NaCl App.

There is also a cheat sheet for this demo available in Tizen Studio that explains the application functionality by highlighting most important code fragments. Cheat sheets are available from the Help menu.



The application is a simple Hello World application. It waits for the message sent from JS and prepares a reply message by appending the received string to the end of the message. When reply is ready it sends the message back to JS where it’s displayed on the screen.

C Code Analysis

The module is one of the main parts of NaCl application. Below two main functions of the module are presented that serve as an entry and an exit point for every NaCl application. Both these functions must be implemented and their name has to be the same as given in the code snippet below, otherwise the code of the application won’t compile.

PPP_InitializeModule() is an entry point for every NaCl plugin and is called just after the module is loaded on the webpage. Interfaces and other resources initialization should be performed inside of it. In this particular case two interfaces are initialized. The first one is the PPB_Messaging interface which implements PostMessage() function that allows the NaCl plugin to send messages to JavaScript. This interface will be used later to send a reply message to the JavaScript. The second interface is PPB_Var interface which is a tool for creation and managing PP_Var objects which are wrappers for JavaScript variables in C code. This interface is used to convert the C-style string to JavaScript variable which is then sent to the JavaScript via PPB_Messaging interface.

PPP_ShutdownModule() is a function that should be left empty (but implemented!). As per the Native Client documentation, this function is used only for some specific use cases in Chrome and shouldn’t be used by the 3rd party developers. You should release any acquired earlier resources here.

The code fragment that shows implementation details of those two functions is presented below.

/* Global pointers to selected browser interfaces. */
const PPB_Messaging* g_messaging_interface;
const PPB_Var* g_var_interface;

/**
 * This is an entry point to this nacl module. It's called while module is being
 * initialized. It's better not to do much here but interface initialization.
 * With <code>get_browser_interface</code> you can get browser interfaces.
 * Implementation of this method is obligatory.
 * @see <code>PPP_InitializeModule</code> in ppp.h file.
 */
PP_EXPORT int32_t PPP_InitializeModule(PP_Module module_id,
                                       PPB_GetInterface get_browser_interface) {
  // Initializing pointers to used browser interfaces.
  g_messaging_interface = (const PPB_Messaging*) get_browser_interface(
      PPB_MESSAGING_INTERFACE);
  g_var_interface = (const PPB_Var*) get_browser_interface(PPB_VAR_INTERFACE);

  return PP_OK;
}

/**
 * An implementation specific function for internal use only. It's better to
 * leave this method empty :) .
 * Implementation of this method is obligatory.
 * @see <code>PPP_ShutdownModule</code> in ppp.h file.
 */
PP_EXPORT void PPP_ShutdownModule() {
}

Another mandatory part when writing a NaCl application in C is the implementation of several functions specific to the PPP_Instance interface. These can be named as per the naming convention but they must be implemented (can be empty functions also). In this example following functions of PPP_Instance were implemented:

Instance_DidCreate() - this function determines what is happening right after the instance was created. You can perform the whole initialization of the instance here. It returns a PP_Bool enum, namelyPP_TRUE if instance creation was successful or PP_FALSE otherwise. In this implementation there is no need for any additional action so it always returns PP_TRUE.
Instance_DidDestroy()- represents what have to be done on instance destruction. This function should release acquired instance specific resources. Our instance does not have anything to release so this function is empty.
Instance_DidChangeView()- called by the browser when the viewport is created or changed in any way. Here is the place to adjust to this change. This sample widget does not use graphics so this function can be left empty.
Instance_DidChangeFocus()- called by the browser when the embedded NaCl module gains or loses focus. Should be left empty in this application.
Instance_HandleDocumentLoad() - this function is not used for Tizen. It returns PP_Bool enum. In every implementation it must return PP_FALSE.
The implementation of those functions is shown below:

/**
 * This function is called by the browser when a new NaCl application instance
 * is created. Here your application starts it's action.
 * @see <code>DidCreate</code> in ppp_instance.h file.
 */
static PP_Bool Instance_DidCreate(PP_Instance instance, uint32_t argc,
                                  const char* argn[], const char* argv[]) {
  return PP_TRUE;
}

/**
 * Called when an instance is destroyed.
 * @see <code>DidDestroy</code> in ppp_instance.h file.
 */
static void Instance_DidDestroy(PP_Instance instance) {
}

/**
 * Called when instance view attributes has changed.
 * @see <code>DidChangeView</code> in ppp_instance.h file.
 */
static void Instance_DidChangeView(PP_Instance pp_instance, PP_Resource view) {
}

/**
 * Called when an instance gained or lost focus.
 * @see <code>DidChangeFocus</code> in ppp_instance.h file.
 */
static void Instance_DidChangeFocus(PP_Instance pp_instance, PP_Bool has_focus) {
}

/**
 * @see <code>HandleDocumentLoad</code> in ppp_instance.h file.
 */
static PP_Bool Instance_HandleDocumentLoad(PP_Instance pp_instance,
                                           PP_Resource pp_url_loader) {
  return PP_FALSE;
}

The next part is not mandatory for the NaCl instance to load but provides the implementation for message receiving which is substantial for our application. In order to implement message receiving we need to implement PPP_Messaging interface. There is only one function that needs to be defined, you can name it any way you prefer. In our example application it’s named Messaging_HandleMessage(). It’s called by the browser upon receiving a message from JavaScript on the web page. In this implementation it’s role is to concatenate a previously defined echo string with the received message and then send it back to the JavaScript. The concatenation is done using the snprintf() function which is part of the C standard library. The char buffer is then converted to the PP_Var object using initialized earlier PPB_Var interface and then send to the JavaScript by calling the PostMessage() method from the PPB_Messaging interface. The implementation of this function is shown below:

const char* kEcho = "Echo from NaCl: ";

/**
 * Handles messages from JS sent by <code>nacl_module.postMessage(...)</code>.
 * @see <code>HandleMessage()</code> in ppp_messaging.h file.
 */
void Messaging_HandleMessage(PP_Instance instance, struct PP_Var message) {
  char str_buff[64];
  uint32_t len;

  // Extract char array from message <code>PP_Var</code> structure.
  const char* message_str = g_var_interface->VarToUtf8(message, &len);
  if (message_str == NULL)
    return;

  snprintf(str_buff, sizeof(str_buff), "%s%s\n", kEcho, message_str);

  // Create <code>PP_Var</code> containing the message body.
  struct PP_Var var_response = g_var_interface->VarFromUtf8(str_buff,
                                                            strlen(str_buff));

  // Post message to the JavaScript layer.
  g_messaging_interface->PostMessage(instance, var_response);
}

This may look like our job is done, but there is one last crucial function left to define which connects the NaCl module with the interfaces we implemented. The PPP_GetInterface() function takes a C-style string as an argument and returns const void pointer. This function is called several times by the browser during application initialization with different PPP interface names (browser keeps the list of all available PPP interfaces). Each execution of that function should check whether the interface with the provided name is implemented. For each of these, this function should return a structure that contains pointers to the interface functions that were implemented. In case the interface with a given name is not implemented NULL should be returned. In our widget two interfaces are implemented, namely PPP_Instance and PPP_Messaging, so we must return pointers to two different structures. This is quite trivial and look like this:

/**
 * Browser uses this method to get implementation of interfaces that this module
 * supports.
 * Implementation of this method is also obligatory.
 * @see <code>PPP_GetInterface</code> in ppp.h file.
 */
PP_EXPORT const void* PPP_GetInterface(const char* interface_name) {

  if (strcmp(interface_name, PPP_INSTANCE_INTERFACE) == 0) {
    // Your module must fill this structure (interface) with proper order
    // (@see ppp.h file) and return it in this case.
    static PPP_Instance instance_interface = {
        &Instance_DidCreate,
        &Instance_DidDestroy,
        &Instance_DidChangeView,
        &Instance_DidChangeFocus,
        &Instance_HandleDocumentLoad
    };
    return &instance_interface;
  }
  if (strcmp(interface_name, PPP_MESSAGING_INTERFACE) == 0) {
    // To handle messages you have to implement PPP_Messaging interface and
    // return it as a pointer to this structure.
    static PPP_Messaging messaging_interface = {
        &Messaging_HandleMessage
    };
    return &messaging_interface;
  }
  return NULL;
}

Summary

This application can be compiled using Tizen Studio or manually with the make program. The application compiled manually can be run in Google Chrome. To run it on Smart TV Emulator you have to build it with Tizen Studio.

When the NaCl module loads, the Status field text will change to “Loaded”. In the NaCl messages section the log will appear: “Echo from NaCl: Hello World from JS” just like on the image below.