Hello World in C


This topic describes the "Hello World in C" sample application implementation.


Samples


This tutorial describes how to implement a simple "Hello World" Native Client (NaCl) application in C. The NaCl module waits for a message from the JavaScript component, creates a reply message by appending the received string to a predefined string, and sends it as a reply back to the JavaScript component, which displays the message on the screen.

The following figure shows the sample application. When the NaCl module has loaded, the "Status" field text changes to "Loaded". In the "NaCl messages" section, the message "Echo from NaCl: Hello World from JS" appears.

Figure 1. Hello World in C application

For information on how to access the sample application cheat sheet and run the application, see Sample-based Tutorials.

To implement the "Hello World" NaCl application in C:

  1. Initialize the module.
    A NaCl module in C must implement the following 2 functions:

    • The PPP_InitializeModule() function is an entry point for the NaCl plugin and is called when the module is loaded on the Web page. You must initialize interfaces and resources in this function, including the following mandatory interfaces:
      • The PPB_Messaging interface implements the PostMessage() function, which allows the NaCl plugin to send messages to the JavaScript component. This interface is used to send the reply message to the JavaScript component.
      • The PPB_Var interface creates and manages PP_Var objects, which are wrappers for JavaScript variables in C code. This interface is used to convert C-style strings to JavaScript variables, which can be sent to the JavaScript component using the PPB_Messaging interface.
        /* Global pointers to selected browser interfaces */
        const PPB_Messaging* g_messaging_interface;
        const PPB_Var* g_var_interface;
        
        /**
         * Entry point to the NaCl module, called while the module is being initialized
         * This function is obligatory; initialize interfaces in this function
         */
        PP_EXPORT int32_t PPP_InitializeModule(PP_Module module_id,
                                               PPB_GetInterface get_browser_interface) {
          // Initialize 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;
        }
        
      • The PPP_ShutdownModule() function is used internally by Google Chrome™ and must be left empty:
        /**
         * Implementation-specific function for internal use only
         * This function is obligatory, but leave it empty
         * @see <code>PPP_ShutdownModule</code> in ppp.h file.
         */
        PP_EXPORT void PPP_ShutdownModule() {
        }
        

    For more information on the above functions, see the "include/ppapi/c/ppp.h" file in your "nacl_sdk/pepper_xx" directory.

  2. Implement the instance-specific functions.
    When developing a NaCl application in C, you must implement all the following functions specific to the PPP_Instance interface, even if they are empty:

    • In the Instance_DidCreate() function, define the actions to perform when the instance is created, such as its initialization logic. The function returns PP_TRUE if the instance creation was successful, or PP_FALSE otherwise.

      In the sample application, no initialization logic is needed, so the function always returns PP_TRUE:

      static PP_Bool Instance_DidCreate(PP_Instance instance, uint32_t argc,
                                        const char* argn[], const char* argv[]) {
        return PP_TRUE;
      }
      
    • In the Instance_DidDestroy() function, define the actions to perform when the instance is destroyed, such as releasing any acquired instance-specific resources.

      In the sample application, the instance has nothing to release, so the function is empty:

      static void Instance_DidDestroy(PP_Instance instance) {
      }
      
    • In the Instance_DidChangeView() function, define the actions to perform when the application viewport is created or changed in any way.

      The sample application does not use graphics, so the function is empty:

      static void Instance_DidChangeView(PP_Instance pp_instance, PP_Resource view) {
      }
      
    • In the Instance_DidChangeFocus() function, define the actions to perform when the embedded NaCl module gains or loses focus.

      This functionality is not needed in the sample application, so the function is empty:

      static void Instance_DidChangeFocus(PP_Instance pp_instance, PP_Bool has_focus) {
      }
      
    • The Instance_HandleDocumentLoad() function is not used in Tizen NaCl applications, and must return PP_FALSE:

      static PP_Bool Instance_HandleDocumentLoad(PP_Instance pp_instance,
                                                 PP_Resource pp_url_loader) {
        return PP_FALSE;
      }
      

    For more information on the above functions, see the "include/ppapi/c/ppp_instance.h" file in your "nacl_sdk/pepper_xx" directory.

  3. To receive messages, implement the Messaging_HandleMessage() function of the PPP_Messaging interface.
    When the NaCl module receives a message from the JavaScript component:

    1. Extract the message from the PP_Var object.
    2. Concatenate the message to the predefined echo string, using the C standard library snprintf() function.
    3. Convert the char buffer to a PP_Var object using the PPB_Var interface.
    4. Send the message to the JavaScript component using the PostMessage() function of the PPB_Messaging interface.
    const char* kEcho = "Echo from NaCl: ";
    
    /**
     * Handles messages from JS sent by the nacl_module.postMessage(...) function
     */
    void Messaging_HandleMessage(PP_Instance instance, struct PP_Var message) {
      char str_buff[64];
      uint32_t len;
    
      // Extract the char array from the message PP_Var 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 a PP_Var containing the message body
      struct PP_Var var_response = g_var_interface->VarFromUtf8(str_buff,
                                                            strlen(str_buff));
    
      // Post the message to the JavaScript layer
      g_messaging_interface->PostMessage(instance, var_response);
    }
    

    For more information on the HandleMessage() function, see the "include/ppapi/c/ppp_messaging.h" file in your "nacl_sdk/pepper_xx" directory.

  4. Connect the interfaces to the NaCl module.
    To connect the implemented interfaces, you must implement the PPP_GetInterface() function, which takes a C-style string as a parameter and returns a const void pointer. The function is called multiple times during application initialization, checking for PPP interfaces that have been implemented. For each implemented interface, return a structure containing pointers to the interface functions:

    /**
     * This mandatory function retrieves the interface implementations that this module supports
     */
    PP_EXPORT const void* PPP_GetInterface(const char* interface_name) {
    
      if (strcmp(interface_name, PPP_INSTANCE_INTERFACE) == 0) {
        // The module must fill this structure (interface) in the following order
        // 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, implement the PPP_Messaging interface and
        // return it as a pointer to this structure
        static PPP_Messaging messaging_interface = {
          &Messaging_HandleMessage
        };
        return &messaging_interface;
      }
      return NULL;
    }
    

    For more information on the PPP_GetInterface() function, see the "include/ppapi/c/ppp.h" file in your "nacl_sdk/pepper_xx" directory.