1 .. _tutorial: 2 3 ###################################### 4 C++ Tutorial: Getting Started (Part 1) 5 ###################################### 6 7 .. contents:: 8 :local: 9 :backlinks: none 10 :depth: 2 11 12 Overview 13 ======== 14 15 This tutorial shows how to build and run a web application using Portable Native 16 Client (PNaCl). This is a client-side application that uses HTML, JavaScript and 17 a Native Client module written in C++. The PNaCl toolchain is used to enable 18 running the Native Client module directly from a web page. 19 20 It's recommended to read the :doc:`Native Client Technical Overview 21 </overview>` prior to going through this tutorial. 22 23 What the application in this tutorial does 24 ------------------------------------------ 25 26 The application in this tutorial shows how to load a Native Client module in a 27 web page, and how to send messages between JavaScript and the C++ code in the 28 Native Client module. In this simple application, the JavaScript code in the web 29 page sends a ``'hello'`` message to the Native Client module. When the Native 30 Client module receives a message, it checks whether the message is equal to the 31 string ``'hello'``. If it is, the Native Client module returns a message saying 32 ``'hello from NaCl'``. A JavaScript alert panel displays the message received 33 from the Native Client module. 34 35 Communication between JavaScript and Native Client modules 36 ---------------------------------------------------------- 37 38 The Native Client programming model supports bidirectional communication between 39 JavaScript and the Native Client module (C/C++ code). Both sides can initiate 40 and respond to messages. In all cases, the communication is asynchronous: The 41 caller (JavaScript or the Native Client module) sends a message, but the caller 42 does not wait for, or may not even expect, a response. This behavior is 43 analogous to client/server communication on the web, where the client posts a 44 message to the server and returns immediately. The Native Client messaging 45 system is part of the Pepper API, and is described in detail in 46 :doc:`Developer's Guide: Messaging System </devguide/coding/message-system>`. 47 It is also similar to the way `web workers 48 <http://en.wikipedia.org/wiki/Web_worker>`_ interact with the main document in 49 JavaScript. 50 51 Step 1: Download and install the Native Client SDK 52 ================================================== 53 54 Follow the instructions on the :doc:`Download </sdk/download>` page to 55 download and install the Native Client SDK. 56 57 .. _tutorial_step_2: 58 59 Step 2: Start a local server 60 ============================ 61 62 To simulate a production environment, the SDK provides a simple web server that 63 can be used to serve the application on ``localhost``. A convenience Makefile 64 rule called ``serve`` is the easiest way to invoke it: 65 66 .. naclcode:: 67 :prettyprint: 0 68 69 $ cd pepper_$(VERSION)/getting_started 70 $ make serve 71 72 .. Note:: 73 :class: note 74 75 The SDK may consist of several "bundles", one per Chrome/Pepper version (see 76 :doc:`versioning information </version>`). In the sample invocation above 77 ``pepper_$(VERSION)`` refers to the specific version you want to use. For 78 example, ``pepper_31``. If you don't know which version you need, use the 79 one labeled ``(stable)`` by ``naclsdk list``. See :doc:`Download the Native 80 Client SDK </sdk/download>` for more details. 81 82 If no port number is specified, the server defaults to port 5103, and can be 83 accessed at ``http://localhost:5103``. 84 85 Any server can be used for the purpose of development. The one provided with the 86 SDK is just a convenience, not a requirement. 87 88 .. _tutorial_step_3: 89 90 Step 3: Set up the Chrome browser 91 ================================= 92 93 PNaCl is enabled by default in Chrome version 31 and later. Please make sure 94 that you have a suitable version to work through this tutorial. It's also 95 important to use a Chrome version that's the same or newer than the SDK bundle 96 used to build the Native Client modules. 97 98 .. Note:: 99 :class: note 100 101 To find out the version of Chrome, type ``about:chrome`` in the address bar. 102 103 For a better development experience, it's also recommended to disable the 104 Chrome cache. Chrome caches resources aggressively; disabling the cache helps 105 make sure that the latest version of the Native Client module is loaded during 106 development. 107 108 * Open Chrome's developer tools by clicking the menu icon |menu-icon| and 109 choosing ``Tools > Developer tools``. 110 * Click the gear icon |gear-icon| in the bottom right corner of the Chrome 111 window. 112 * Under the "General" settings, check the box next to "Disable cache (while 113 DevTools is open)". 114 * Keep the Developer Tools pane open while developing Native Client 115 applications. 116 117 .. |menu-icon| image:: /images/menu-icon.png 118 .. |gear-icon| image:: /images/gear-icon.png 119 120 Step 4: Stub code for the tutorial 121 ================================== 122 123 The stub code for the tutorial is avalable in the SDK, in 124 ``pepper_$(VERSION)/getting_started/part1``. It contains the following files: 125 126 * ``index.html``: Contains the HTML layout of the page as well as the JavaScript 127 code that interacts with the Native Client module. 128 129 The Native Client module is included in the page with an ``<embed>`` tag that 130 points to a manifest file. 131 * ``hello_tutorial.nmf``: A manifest file that's used to point the HTML to the 132 Native Client module and optionally provide additional commands to the PNaCl 133 translator that is part of the Chrome browser. 134 * ``hello_tutorial.cc``: C++ code for a simple Native Client module. 135 * ``Makefile``: Compilation commands to build the **pexe** (portable executable) 136 from the C++ code in ``hello_tutorial.cc``. 137 138 It's a good idea to take a look at these files now---they contain a large amount 139 of comments that help explain their structure and contents. For more details 140 on the structure of a typical Native Client application, see 141 :doc:`Application Structure </devguide/coding/application-structure>`. 142 143 The stub code is intentionally very minimal. The C++ code does not do anything 144 except correctly initialize itself. The JavaScript code waits for the Native 145 Client module to load and changes the status text on the web page accordingly. 146 147 .. _tutorial_step_5: 148 149 Step 5: Compile the Native Client module and run the stub application 150 ===================================================================== 151 152 To compile the Native Client module, run ``make``: 153 154 .. naclcode:: 155 :prettyprint: 0 156 157 $ cd pepper_$(VERSION)/getting_started/part1 158 $ make 159 160 Since the sample is located within the SDK tree, the Makefile knows how to find 161 the PNaCl toolchain automatically and use it to build the module. If you're 162 building applications outside the NaCl SDK tree, you should set the 163 ``$NACL_SDK_ROOT`` environment variable. See :doc:`Building Native Client 164 Modules </devguide//devcycle/building>` for more details. 165 166 Assuming the local server was started according to the instructions in 167 :ref:`Step 2 <tutorial_step_2>`, you can now load the sample by pointing Chrome 168 to ``http://localhost:5103/part1``. Chrome should load the Native Client module 169 successfully and the Status text should change from "LOADING..." to "SUCCESS". 170 If you run into problems, check out the :ref:`Troubleshooting section 171 <tutorial_troubleshooting>` below. 172 173 Step 6: Modify the JavaScript code to send a message to the Native Client module 174 ================================================================================ 175 176 In this step, you'll modify the web page (``index.html``) to send a message to 177 the Native Client module after the page loads the module. 178 179 Look for the JavaScript function ``moduleDidLoad()``, and add new code to send 180 a 'hello' message to the module. The new function should look as follows: 181 182 .. naclcode:: 183 184 function moduleDidLoad() { 185 HelloTutorialModule = document.getElementById('hello_tutorial'); 186 updateStatus('SUCCESS'); 187 // Send a message to the Native Client module 188 HelloTutorialModule.postMessage('hello'); 189 } 190 191 Step 7: Implement a message handler in the Native Client module 192 =============================================================== 193 194 In this step, you'll modify the Native Client module (``hello_tutorial.cc``) to 195 respond to the message received from the JavaScript code in the application. 196 Specifically, you'll: 197 198 * Implement the ``HandleMessage()`` member function of the module instance. 199 * Use the ``PostMessage()`` member function to send a message from the module to 200 the JavaScript code. 201 202 First, add code to define the variables used by the Native Client module (the 203 'hello' string you're expecting to receive from JavaScript and the reply string 204 you want to return to JavaScript as a response). In the file 205 ``hello_tutorial.cc``, add this code after the ``#include`` statements: 206 207 .. naclcode:: 208 209 namespace { 210 // The expected string sent by the browser. 211 const char* const kHelloString = "hello"; 212 // The string sent back to the browser upon receipt of a message 213 // containing "hello". 214 const char* const kReplyString = "hello from NaCl"; 215 } // namespace 216 217 Now, implement the ``HandleMessage()`` member function to check for 218 ``kHelloString`` and return ``kReplyString.`` Look for the following line: 219 220 .. naclcode:: 221 222 // TODO(sdk_user): 1. Make this function handle the incoming message. 223 224 Populate the member function with code, as follows: 225 226 .. naclcode:: 227 228 virtual void HandleMessage(const pp::Var& var_message) { 229 if (!var_message.is_string()) 230 return; 231 std::string message = var_message.AsString(); 232 pp::Var var_reply; 233 if (message == kHelloString) { 234 var_reply = pp::Var(kReplyString); 235 PostMessage(var_reply); 236 } 237 } 238 239 See the Pepper API documentation for additional information about the 240 `pp::Instance.HandleMessage 241 </native-client/pepper_stable/cpp/classpp_1_1_instance.html#a5dce8c8b36b1df7cfcc12e42397a35e8>`_ 242 and `pp::Instance.PostMessage 243 </native-client/pepper_stable/cpp/classpp_1_1_instance.html#a67e888a4e4e23effe7a09625e73ecae9>`_ 244 member functions. 245 246 Step 8: Compile the Native Client module and run the application again 247 ====================================================================== 248 249 Compile the Native Client module by running the ``make`` command again. 250 251 Re-run the application by reloading ``http://localhost:5103/part1`` in Chrome. 252 253 After Chrome loads the Native Client module, you should see an alert panel 254 appear with the message sent from the module. 255 256 .. _tutorial_troubleshooting: 257 258 Troubleshooting 259 =============== 260 261 If your application doesn't run, see :ref:`Step 3 <tutorial_step_3>` above to 262 verify that you've set up your environment correctly, including both the Chrome 263 browser and the local server. Make sure that you're running a correct version of 264 Chrome, which is also greater or equal than the SDK bundle version you are 265 using. 266 267 Another useful debugging aid is the Chrome JavaScript console (available via the 268 ``Tools`` menu in Chrome). Examine it for clues about what went wrong. For 269 example, if there's a message saying "NaCl module crashed", there is a 270 possibility that the Native Client module has a bug; :doc:`debugging 271 </devguide/devcycle/debugging>` may be required. 272 273 There's more information about troubleshooting in the documentation: 274 275 * :ref:`FAQ Troubleshooting <faq_troubleshooting>`. 276 * The :doc:`Progress Events </devguide/coding/progress-events>` document 277 contains some useful information about handling error events. 278 279 Next steps 280 ========== 281 282 * See the :doc:`Application Structure </devguide/coding/application-structure>` 283 chapter in the Developer's Guide for information about how to structure a 284 Native Client module. 285 * Check the `C++ Reference </native-client/pepper_stable/cpp>`_ for details 286 about how to use the Pepper APIs. 287 * Browse through the source code of the SDK examples (in the ``examples`` 288 directory) to learn additional techniques for writing Native Client 289 applications and using the Pepper APIs. 290 * See the :doc:`Building </devguide/devcycle/building>`, :doc:`Running 291 </devguide/devcycle/running>`, and :doc:`Debugging pages 292 </devguide/devcycle/debugging>` for information about how to build, run, and 293 debug Native Client applications. 294 * Check the `naclports <http://code.google.com/p/naclports/>`_ project to see 295 what libraries have been ported for use with Native Client. If you port an 296 open-source library for your own use, we recommend adding it to naclports 297 (see `How to check code into naclports 298 <http://code.google.com/p/naclports/wiki/HowTo_Checkin>`_). 299