1 .. _devcycle-native-client-modules: 2 3 ##################### 4 Native Client Modules 5 ##################### 6 7 This document describes the classes and functions that you need to implement in 8 a Native Client module in order for Chrome to load, initialize, and run it. The 9 requirements are the same regardless of whether or not the module uses PNaCl, 10 but depend on whether the module is written in C or C++. 11 12 .. contents:: 13 :local: 14 :backlinks: none 15 :depth: 2 16 17 Introduction 18 ============ 19 20 Native Client modules do not have a ``main()`` function. When a module loads, 21 the Native Client runtime calls the code in the module to create an instance and 22 initialize the interfaces for the APIs the module uses. This initialization 23 sequence depends on whether the module is written in C or C++ and requires that 24 you implement specific functions in each case. 25 26 27 Writing modules in C 28 ==================== 29 30 The C API uses a prefix convention to show whether an interface is implemented 31 in the browser or in a module. Interfaces starting with ``PPB_`` (which can be 32 read as "Pepper *browser*") are implemented in the browser and they are called 33 from your module. Interfaces starting with ``PPP_`` ("Pepper *plugin*") are 34 implemented in the module; they are called from the browser and will execute on 35 the main thread of the module instance. 36 37 When you implement a Native Client module in C you must include these components: 38 39 * The functions ``PPP_InitializeModule`` and ``PPP_GetInterface`` 40 * Code that implements the interface ``PPP_Instance`` and any other C interfaces 41 that your module uses 42 43 For each PPP interface, you must implement all of its functions, create the 44 struct through which the browser calls the interface, and insure that the 45 function ``PPP_GetInterface`` returns the appropriate struct for the interface. 46 47 For each PPB interface, you must declare a pointer to the interface and 48 initialize the pointer with a call to ``get_browser`` inside 49 ``PPP_InitializeModule``. 50 51 These steps are illustrated in the code excerpt below, which shows the 52 implementation and initialization of the required ``PPP_Instance`` 53 interface. The code excerpt also shows the initialization of three additional 54 interfaces which are not required: ``PPB_Instance`` (through which the Native 55 Client module calls back to the browser) and ``PPB_InputEvent`` and 56 ``PPP_InputEvent``. 57 58 .. naclcode:: 59 60 #include <stdlib.h> 61 #include <string.h> 62 #include "ppapi/c/pp_errors.h" 63 #include "ppapi/c/ppp.h" 64 // Include the interface headers. 65 // PPB APIs describe calls from the module to the browser. 66 // PPP APIs describe calls from the browser to the functions defined in your module. 67 #include "ppapi/c/ppb_instance.h" 68 #include "ppapi/c/ppp_instance.h" 69 #include "ppapi/c/ppb_input_event.h" 70 #include "ppapi/c/ppp_input_event.h" 71 72 // Create pointers for each PPB interface that your module uses. 73 static PPB_Instance* ppb_instance_interface = NULL; 74 static PPB_InputEvent* ppb_input_event_interface = NULL; 75 76 // Define all the functions for each PPP interface that your module uses. 77 // Here is a stub for the first function in PPP_Instance. 78 static PP_Bool Instance_DidCreate(PP_Instance instance, 79 uint32_t argc, 80 const char* argn[], 81 const char* argv[]) { 82 return PP_TRUE; 83 } 84 // ... more API functions ... 85 86 // Define PPP_GetInterface. 87 // This function should return a non-NULL value for every interface you are using. 88 // The string for the name of the interface is defined in the interface's header file. 89 // The browser calls this function to get pointers to the interfaces that your module implements. 90 PP_EXPORT const void* PPP_GetInterface(const char* interface_name) { 91 // Create structs for each PPP interface. 92 // Assign the interface functions to the data fields. 93 if (strcmp(interface_name, PPP_INSTANCE_INTERFACE) == 0) { 94 static PPP_Instance instance_interface = { 95 &Instance_DidCreate, 96 // The definitions of these functions are not shown 97 &Instance_DidDestroy, 98 &Instance_DidChangeView, 99 &Instance_DidChangeFocus, 100 &Instance_HandleDocumentLoad 101 }; 102 return &instance_interface; 103 } 104 105 if (strcmp(interface_name, PPP_INPUT_EVENT_INTERFACE) == 0) { 106 static PPP_InputEvent input_interface = { 107 // The definition of this function is not shown. 108 &Instance_HandleInput, 109 }; 110 return &input_interface; 111 } 112 // Return NULL for interfaces that you do not implement. 113 return NULL; 114 } 115 116 // Define PPP_InitializeModule, the entry point of your module. 117 // Retrieve the API for the browser-side (PPB) interfaces you will use. 118 PP_EXPORT int32_t PPP_InitializeModule(PP_Module a_module_id, PPB_GetInterface get_browser) { 119 ppb_instance_interface = (PPB_Instance*)(get_browser(PPB_INSTANCE_INTERFACE)); 120 ppb_input_event_interface = (PPB_InputEvent*)(get_browser(PPB_INPUT_EVENT_INTERFACE)); 121 return PP_OK; 122 } 123 124 125 Writing modules in C++ 126 ====================== 127 128 When you implement a Native Client module in C++ you must include these components: 129 130 * The factory function called ``CreateModule()`` 131 * Code that defines your own Module class (derived from the ``pp::Module`` 132 class) 133 * Code that defines your own Instance class (derived from the ``pp:Instance`` 134 class) 135 136 In the "Hello tutorial" example (in the ``getting_started/part1`` directory of 137 the NaCl SDK), these three components are specified in the file 138 ``hello_tutorial.cc``. Here is the factory function: 139 140 .. naclcode:: 141 142 namespace pp { 143 Module* CreateModule() { 144 return new HelloTutorialModule(); 145 } 146 } 147 148 The ``CreateModule()`` factory function is the main binding point between a 149 module and the browser, and serves as the entry point into the module. The 150 browser calls ``CreateModule()`` when a module is first loaded; this function 151 returns a Module object derived from the ``pp::Module`` class. The browser keeps 152 a singleton of the Module object. 153 154 Below is the Module class from the "Hello tutorial" example: 155 156 .. naclcode:: 157 158 class HelloTutorialModule : public pp::Module { 159 public: 160 HelloTutorialModule() : pp::Module() {} 161 virtual ~HelloTutorialModule() {} 162 163 virtual pp::Instance* CreateInstance(PP_Instance instance) { 164 return new HelloTutorialInstance(instance); 165 } 166 }; 167 168 The Module class must include a ``CreateInstance()`` method. The browser calls 169 the ``CreateInstance()`` method every time it encounters an ``<embed>`` element 170 on a web page that references the same module. The ``CreateInstance()`` function 171 creates and returns an Instance object derived from the ``pp::Instance`` class. 172 173 Below is the Instance class from the "Hello tutorial" example: 174 175 .. naclcode:: 176 177 class HelloTutorialInstance : public pp::Instance { 178 public: 179 explicit HelloTutorialInstance(PP_Instance instance) : pp::Instance(instance) {} 180 virtual ~HelloTutorialInstance() {} 181 182 virtual void HandleMessage(const pp::Var& var_message) {} 183 }; 184 185 186 As in the example above, the Instance class for your module will likely include 187 an implementation of the ``HandleMessage()`` function. The browser calls an 188 instance's ``HandleMessage()`` function every time the JavaScript code in an 189 application calls ``postMessage()`` to send a message to the instance. See the 190 :doc:`Native Client messaging system<message-system>` for more information about 191 how to send messages between JavaScript code and Native Client modules. 192 193 While the ``CreateModule()`` factory function, the ``Module`` class, and the 194 ``Instance`` class are required for a Native Client application, the code 195 samples shown above don't actually do anything. Subsequent documents in the 196 Developer's Guide build on these code samples and add more interesting 197 functionality. 198