OLD | NEW |
1 .. _tutorial: | 1 .. _tutorial: |
2 | 2 |
3 ######################## | 3 ############################# |
4 Getting Started Tutorial | 4 C++ Tutorial: Getting Started |
5 ######################## | 5 ############################# |
6 | 6 |
7 This is the tutorial. | 7 .. contents:: |
8 | 8 :local: |
| 9 :backlinks: none |
| 10 :depth: 2 |
| 11 |
| 12 Overview |
| 13 ======== |
| 14 |
| 15 This tutorial shows you how to create, compile, and run a Native Client web |
| 16 application. The Native Client module you will create as part of the web |
| 17 application will be written in C++. |
| 18 |
| 19 We recommend reading the :doc:`Native Client Technical Overview |
| 20 <../overview>` prior to going through this tutorial. |
| 21 |
| 22 Parts in a Native Client application |
| 23 ------------------------------------ |
| 24 |
| 25 A Native Client web application consists of at least three parts: |
| 26 **TODO(binji)**: This is duplicated in the technical overview. Make sure it is |
| 27 consistent in each. |
| 28 |
| 29 * A **web page** (*\*.html*) |
| 30 |
| 31 The web page can include HTML, JavaScript, and CSS (the JavaScript and CSS |
| 32 can also go in separate .js and .css files). |
| 33 |
| 34 * A **Native Client module** (*\*.c* or *\*.cc* before compiling; *\*.nexe* |
| 35 after compiling) |
| 36 |
| 37 Native Client modules can be written in C or C++. Modules use the Pepper API, |
| 38 included in the SDK, as a bridge between the browser and the modules. |
| 39 |
| 40 * A **Manifest** file (*\*.nmf*) |
| 41 |
| 42 Browsers use an application's manifest file to determine which compiled Native |
| 43 Client module to load based on the instruction set architecture of the user's |
| 44 machine (e.g., x86-32, x86-64, or ARM). |
| 45 |
| 46 What the application in this tutorial does |
| 47 ------------------------------------------ |
| 48 |
| 49 The application in this tutorial shows how to load a Native Client module in a |
| 50 web page, and how to send messages between JavaScript code and the C or C++ |
| 51 code in the Native Client module. In this simple application, the JavaScript |
| 52 code in the web page sends a 'hello' message to the Native Client module. When |
| 53 the Native Client module receives a message, it checks whether the message is |
| 54 equal to the string 'hello'. If it is, the Native Client module returns a |
| 55 message saying 'hello from NaCl'. A JavaScript alert panel displays the message |
| 56 received from the Native Client module. |
| 57 |
| 58 This tutorial also shows you how to create a set of template files that you can |
| 59 use as a starting point for a Native Client application. The template code sets |
| 60 up a simple message handler on the Native Client side, and includes boilerplate |
| 61 code in the HTML file for adding an event listener to the web page to receive |
| 62 messages from the Native Client module. |
| 63 |
| 64 Communication between JavaScript code and Native Client modules |
| 65 --------------------------------------------------------------- |
| 66 |
| 67 Communication between JavaScript code in the browser and C or C++ code in a |
| 68 Native Client module is two-way: JavaScript code can send messages to the |
| 69 Native Client module; the C or C++ code can respond to messages from |
| 70 JavaScript, or it can initiate its own messages to JavaScript. In all cases, |
| 71 the communication is asynchronous: The caller (the JavaScript code in the |
| 72 browser or the C/C++ code in the Native Client module) sends a message, but the |
| 73 caller does not wait for, or may not even expect, a response. This behavior is |
| 74 analogous to client/server communication on the web, where the client posts a |
| 75 message to the server and returns immediately. The Native Client messaging |
| 76 system is part of the Pepper API, and is described in detail in the |
| 77 :doc:`Messaging System <coding/message-system>` chapter in the Developer's |
| 78 Guide. |
| 79 |
| 80 Step 1: Download and install the Native Client SDK |
| 81 ================================================== |
| 82 |
| 83 Follow the instructions on the :doc:`Download <../sdk/download>` page to |
| 84 download and install the Native Client SDK. |
| 85 |
| 86 .. Note:: |
| 87 :class: caution |
| 88 |
| 89 **Important:** A number of tools in the SDK require Python to run. Python is |
| 90 typically included on Mac and Linux systems, but not on Windows systems. To |
| 91 check whether you have Python installed on your system, enter the |
| 92 '``python``' command on the command line; you should get the interactive |
| 93 Python prompt (``>>>``). On Mac systems, you also need to install '``make``' |
| 94 in order to build and run the examples in the SDK; one easy way to get |
| 95 '``make``', along with several other useful tools, is to install Xcode |
| 96 Developer Tools. Follow the instructions at the top of the :doc:`Download |
| 97 <../sdk/download>` page if you need to install Python and/or Xcode |
| 98 Developer Tools. |
| 99 |
| 100 Step 2: Start a local server |
| 101 ============================ |
| 102 |
| 103 TODO(binji): This is not necessary anymore; we can use ``make run``. Some of |
| 104 the information about why you need a webserver is still useful though... |
| 105 Remove? |
| 106 |
| 107 To protect against security vulnerabilities, you must load Native Client |
| 108 modules from a web server (either remote or local). **Simply dragging and |
| 109 dropping Native Client files into the browser address bar will not work.** For |
| 110 more information, read about the `Same Origin Policy |
| 111 <http://www.w3.org/Security/wiki/Same_Origin_Policy>`_, which protects the |
| 112 user's file system from outside access. |
| 113 |
| 114 The Native Client SDK includes a simple Python web server that you can use to |
| 115 run applications that you build (including the application in this tutorial). |
| 116 The server is located in the tools directory. To start the web server, go to |
| 117 the examples directory in the SDK bundle that you are using and run the |
| 118 ``httpd.py`` script. For example, if you are using the ``pepper_28`` bundle, |
| 119 run the following commands: |
| 120 |
| 121 .. naclcode:: |
| 122 :prettyprint: 0 |
| 123 |
| 124 cd pepper_28/examples |
| 125 python ../tools/httpd.py |
| 126 |
| 127 If you don't specify a port number, the server defaults to port 5103, and you |
| 128 can access the server at http://localhost:5103. |
| 129 |
| 130 Of course, you don't have to use the server included in the SDK---any web server |
| 131 will do. If you prefer to use another web server already installed on your |
| 132 system, that's fine. Note also that there are ways to run Native Client |
| 133 applications during development without a server, but these techniques require |
| 134 you to create additional files for your application (see :doc:`Running Native |
| 135 Client Applications <devcycle/running>` for details). For this tutorial, |
| 136 your application must come from a server. |
| 137 |
| 138 .. _step_3: |
| 139 |
| 140 Step 3: Set up Google Chrome |
| 141 ============================ |
| 142 |
| 143 Set up the Chrome browser as follows: |
| 144 |
| 145 a. Make sure you are using the minimum required version of Chrome. |
| 146 |
| 147 * Your version of Chrome must be equal to or greater than the version of your |
| 148 Pepper bundle. For example, if you're developing with the ``pepper_28`` |
| 149 bundle, you must use Google Chrome version 28 or greater. To find out what |
| 150 version of Chrome you're using, type ``about:chrome`` or ``about:version`` |
| 151 in the Chrome address bar. |
| 152 |
| 153 b. Enable the Native Client flag in Chrome. (Native Client is enabled by |
| 154 default for applications distributed through the Chrome Web Store. To run |
| 155 Native Client applications that are not distributed through the Chrome Web |
| 156 Store, e.g., applications that you build and run locally, you must |
| 157 specifically enable the Native Client flag in Chrome.) |
| 158 |
| 159 * Type ``about:flags`` in the Chrome address bar and scroll down to "Native |
| 160 Client". |
| 161 * If the link below "Native Client" says "Disable", then Native Client is |
| 162 already enabled and you don't need to do anything else. |
| 163 * If the link below "Native Client" says "Enable", click the "Enable" link, |
| 164 scroll down to the bottom of the page, and click the "Relaunch Now" button. |
| 165 All browser windows will restart when you relaunch Chrome. |
| 166 |
| 167 c. Disable the Chrome cache. (Chrome caches resources aggressively; you should |
| 168 disable the cache whenever you are developing a Native Client application in |
| 169 order to make sure Chrome loads new versions of your application.) |
| 170 |
| 171 * Open Chrome's developer tools by clicking the menu icon |menu-icon| and |
| 172 choosing Tools > Developer tools. |
| 173 * Click the gear icon |gear-icon| in the bottom right corner of the Chrome |
| 174 window. |
| 175 * Under the "General" settings, check the box next to "Disable cache". |
| 176 |
| 177 .. |menu-icon| image:: /images/menu-icon.png |
| 178 .. |gear-icon| image:: /images/gear-icon.png |
| 179 |
| 180 Step 4: Create a set of stub files for your application |
| 181 ======================================================= |
| 182 |
| 183 Create a set of stub files as follows: |
| 184 |
| 185 a. Download `hello_tutorial.zip |
| 186 <https://developers.google.com/native-client/devguide/hello_tutorial.zip>`_. |
| 187 |
| 188 b. Unzip hello_tutorial.zip: |
| 189 |
| 190 * On Mac/Linux, run the command "``unzip hello_tutorial.zip``" in a Terminal |
| 191 window. |
| 192 * On Windows, right-click on the .zip file and select "Extract All..." A |
| 193 dialog box will open; enter a location and click "Extract". |
| 194 |
| 195 c. Unzipping hello_tutorial.zip creates a directory called ``hello_tutorial`` |
| 196 with the following files: |
| 197 |
| 198 * ``hello_tutorial.html`` |
| 199 * ``hello_tutorial.cc`` |
| 200 * ``hello_tutorial.nmf`` |
| 201 * ``Makefile`` |
| 202 * ``make.bat`` (for Windows) |
| 203 |
| 204 d. Move the ``hello_tutorial`` directory so that it's under the ``examples`` |
| 205 directory where you started the local server. Its location should be, e.g., |
| 206 ``pepper_28/examples/hello_tutorial``. |
| 207 |
| 208 * On Windows, depending on the location you entered when you unzipped the |
| 209 file, there may be two ``hello_tutorial`` directories—one nested within |
| 210 the other. Move only the inner (nested) directory to the ``examples`` |
| 211 directory. |
| 212 |
| 213 .. Note:: |
| 214 :class: note |
| 215 |
| 216 **Note regarding the location of project directories:** |
| 217 |
| 218 * In this tutorial, you are adding the ``hello_tutorial`` directory under the |
| 219 ``examples`` directory because the ``examples`` directory is where your |
| 220 local server is running, ready to serve your tutorial application. You can |
| 221 place your project directory anywhere on your file system, as long as that |
| 222 location is being served by your server. |
| 223 * If you do place the ``hello_tutorial`` project directory in another |
| 224 location, you must set the `environment variable |
| 225 <http://en.wikipedia.org/wiki/Environment_variable>`_ ``NACL_SDK_ROOT`` to |
| 226 point to the top-level directory of the bundle you are using (e.g., |
| 227 ``<location-where-you-installed-the-SDK>/pepper_28``) in order for the |
| 228 Makefile that's included in the project directory to work. |
| 229 * If you use the location recommended above |
| 230 (``pepper_28/examples/hello_tutorial``), be careful when you update the |
| 231 SDK. The command '``naclsdk update pepper_28 --force``' will overwrite the |
| 232 ``pepper_28`` directory, so move any project directories you want to keep |
| 233 to another location. |
| 234 |
| 235 Step 5: Compile the Native Client module and run the stub application |
| 236 ===================================================================== |
| 237 |
| 238 The files you downloaded in the previous step constitute a stub application |
| 239 that simply loads a Native Client module into a web page and updates a |
| 240 ``<div>`` element on the page with the status of the module load. |
| 241 |
| 242 To compile the Native Client module ``hello_tutorial.cc,`` run '``make``': |
| 243 |
| 244 .. naclcode:: |
| 245 :prettyprint: 0 |
| 246 |
| 247 cd pepper_28/examples/hello_tutorial |
| 248 make |
| 249 |
| 250 The '``make``' command runs the necessary compile and link commands to produce |
| 251 three executable Native Client modules (for the x86-32, x86-64, and ARM |
| 252 architectures). The executable files are named as follows: |
| 253 |
| 254 * ``hello_tutorial_x86_32.nexe`` |
| 255 * ``hello_tutorial_x86_64.nexe`` |
| 256 * ``hello_tutorial_arm.nexe`` |
| 257 |
| 258 Assuming you are using the local server and the project directory specified |
| 259 above, you can load the ``hello_tutorial.html`` web page into Chrome by visiting |
| 260 the following URL: http://localhost:5103/hello_tutorial/hello_tutorial.html. If |
| 261 Chrome loads the Native Client module successfully, the Status display on the |
| 262 page should change from "LOADING..." to "SUCCESS". |
| 263 |
| 264 Step 6: Review the code in the stub application |
| 265 =============================================== |
| 266 |
| 267 The section highlights some of the code in the stub application. |
| 268 |
| 269 Makefile |
| 270 ``Makefile`` contains the compile and link commands to build the executable |
| 271 Native Client modules (.nexe files) for your application. The Native Client |
| 272 SDK includes multiple GCC‑based toolchains to build modules for multiple |
| 273 architectures (x86 and ARM) using different implementations of the C library |
| 274 (`newlib <http://www.sourceware.org/newlib/>`_ and `glibc |
| 275 <http://www.gnu.org/software/libc/>`_). The commands in the tutorial |
| 276 ``Makefile`` build the application using the newlib C library for the x86 and |
| 277 ARM architectures. The commands use the toolchains located in the |
| 278 ``pepper_28/toolchain/<platform>_x86_newlib`` and ``<platform>_arm_newlib`` |
| 279 directories. For information about how to use Makefiles and the '``make``' |
| 280 command, see the `GNU 'make' manual |
| 281 <http://www.gnu.org/software/make/manual/make.html>`_. |
| 282 |
| 283 hello_tutorial.nmf |
| 284 ``hello_tutorial.nmf`` is a Native Client manifest file that tells Chrome |
| 285 which compiled Native Client module (.nexe) to load based on the instruction |
| 286 set architecture of the user's machine (e.g., x86-32, x86-64, or ARM). For |
| 287 applications compiled using glibc, manifest files must also specify the |
| 288 shared libraries that the applications use. |
| 289 |
| 290 hello_tutorial.html |
| 291 ``hello_tutorial.html`` is the web page that corresponds to your application. |
| 292 The page includes an ``<embed>`` element that loads the compiled Native |
| 293 Client module: |
| 294 |
| 295 .. naclcode:: |
| 296 |
| 297 <div id="listener"> |
| 298 <script type="text/javascript"> |
| 299 var listener = document.getElementById('listener'); |
| 300 listener.addEventListener('load', moduleDidLoad, true); |
| 301 listener.addEventListener('message', handleMessage, true); |
| 302 </script> |
| 303 |
| 304 <embed name="nacl_module" |
| 305 id="hello_tutorial" |
| 306 width=0 height=0 |
| 307 src="hello_tutorial.nmf" |
| 308 type="application/x-nacl" /> |
| 309 </div> |
| 310 |
| 311 The ``src`` attribute in the ``<embed>`` element points to the Native Client |
| 312 manifest file, which tells the browser which .nexe file to load based on the |
| 313 instruction set architecture of the user's machine. The ``width`` and |
| 314 ``height`` attributes in the ``<embed>`` element are set to 0 because the |
| 315 Native Client module in this example does not have any graphical component. |
| 316 The ``type`` attribute declares the MIME type to be ``x-nacl``, i.e., an |
| 317 executable Native Client module. |
| 318 |
| 319 The ``<embed>`` element is wrapped inside a ``<div>`` element that has two |
| 320 event listeners attached—one for the 'load' event, which fires when the |
| 321 browser successfully loads the Native Client module, and one for the |
| 322 'message' event, which fires when the Native Client module uses the |
| 323 ``PostMessage()`` method (in the `pp::Instance |
| 324 <https://developers.google.com/native-client/peppercpp/classpp_1_1_instance>`_ |
| 325 class) to send a message to the JavaScript code in the application. This |
| 326 technique of attaching the event listeners to a parent ``<div>`` element |
| 327 (rather than directly to the ``<embed>`` element) is used to ensure that the |
| 328 event listeners are active before the module 'load' event fires. |
| 329 |
| 330 The simple event handlers in this tutorial are implemented in the |
| 331 ``moduleDidLoad()`` and ``handleMessage()`` JavaScript functions. |
| 332 ``moduleDidLoad()`` changes the text inside the 'status_field' ``<div>`` |
| 333 element. handleMessage() displays the content of messages sent from the |
| 334 Native Client module in a browser alert panel. For a description of 'load', |
| 335 'message', and other Native Client events, see the :doc:`Progress Events |
| 336 <coding/progress-events>` chapter of the Developer's Guide. |
| 337 |
| 338 hello_tutorial.cc |
| 339 Native Client includes the concept of modules and instances: |
| 340 |
| 341 * A **module** is C or C++ code compiled into an executable .nexe file. |
| 342 * An **instance** is a rectangle on a web page that is managed by a module. |
| 343 The rectangle can have dimensions 0x0, in which case the instance does not |
| 344 have a visual component on the web page. An instance is created by |
| 345 including an ``<embed>`` element in a web page. A module may be included in |
| 346 a web page multiple times by using multiple ``<embed>`` elements that refer |
| 347 to the module; in this case the Native Client runtime system loads the |
| 348 module once and creates multiple instances that are managed by the module. |
| 349 |
| 350 The example in this tutorial includes one module |
| 351 (``hello_tutorial_x86_32.nexe``, ``hello_tutorial_x86_64.nexe``, or |
| 352 ``hello_tutorial_arm.nexe``, depending on the instruction set architecture of |
| 353 the user's machine), and one instance (one ``<embed>`` element that loads the |
| 354 module). The source code for the module is in the file ``hello_tutorial.cc``. |
| 355 This source code contains the minimum code required in a C++ Native Client |
| 356 module—an implementation of the `Instance |
| 357 <https://developers.google.com/native-client/peppercpp/classpp_1_1_instance>`_ |
| 358 and `Module |
| 359 <https://developers.google.com/native-client/peppercpp/classpp_1_1_module>`_ |
| 360 classes. These implementations don't actually do anything yet. |
| 361 |
| 362 Step 7: Modify the web page to send a message to the Native Client module |
| 363 ========================================================================= |
| 364 |
| 365 In this step, you'll modify the web page (``hello_tutorial.html``) to send a |
| 366 message to the Native Client module after the page loads the module. |
| 367 |
| 368 Look for the JavaScript function ``moduleDidLoad()``, and add the new code below |
| 369 (indicated by boldface type) to send a 'hello' message to the Native Client |
| 370 module: |
| 371 |
| 372 ..naclcode:: |
| 373 |
| 374 function moduleDidLoad() { |
| 375 HelloTutorialModule = document.getElementById('hello_tutorial'); |
| 376 updateStatus('SUCCESS'); |
| 377 // Send a message to the NaCl module. |
| 378 HelloTutorialModule.postMessage('hello'); |
| 379 } |
| 380 |
| 381 Step 8: Implement a message handler in the Native Client module |
| 382 =============================================================== |
| 383 |
| 384 In this step, you'll modify the Native Client module (``hello_tutorial.cc``) to |
| 385 respond to the message received from the JavaScript code in the application. |
| 386 Specifically, you'll: |
| 387 |
| 388 * implement the ``HandleMessage()`` function for the module, and |
| 389 * use the ``PostMessage()`` function to send a message from the module to the |
| 390 JavaScript code |
| 391 |
| 392 First, add code to define the variables used by the Native Client module (the |
| 393 'hello' string you're expecting to receive from JavaScript and the reply string |
| 394 you want to return to JavaScript as a response). In the file |
| 395 ``hello_tutorial.cc``, add this code after the ``#include`` statements: |
| 396 |
| 397 .. naclcode:: |
| 398 |
| 399 namespace { |
| 400 // The expected string sent by the browser. |
| 401 const char* const kHelloString = "hello"; |
| 402 // The string sent back to the browser upon receipt of a message |
| 403 // containing "hello". |
| 404 const char* const kReplyString = "hello from NaCl"; |
| 405 } // namespace |
| 406 |
| 407 Now, implement the ``HandleMessage()`` method to check for ``kHelloString`` and |
| 408 return ``kReplyString.`` Look for the following line: |
| 409 |
| 410 .. naclcode:: |
| 411 |
| 412 // TODO(sdk_user): 1. Make this function handle the incoming message. |
| 413 |
| 414 Replace the above line with the boldface code below: |
| 415 |
| 416 .. naclcode:: |
| 417 |
| 418 virtual void HandleMessage(const pp::Var& var_message) { |
| 419 if (!var_message.is_string()) |
| 420 return; |
| 421 std::string message = var_message.AsString(); |
| 422 pp::Var var_reply; |
| 423 if (message == kHelloString) { |
| 424 var_reply = pp::Var(kReplyString); |
| 425 PostMessage(var_reply); |
| 426 } |
| 427 } |
| 428 |
| 429 See the Pepper API documentation for additional information about the |
| 430 `pp::Instance.HandleMessage |
| 431 <https://developers.google.com/native-client/peppercpp/classpp_1_1_instance.html
#a5dce8c8b36b1df7cfcc12e42397a35e8>`_ |
| 432 and `pp::Instance.PostMessage |
| 433 <https://developers.google.com/native-client/peppercpp/classpp_1_1_instance.html
#a67e888a4e4e23effe7a09625e73ecae9>`_ |
| 434 methods. |
| 435 |
| 436 Step 9: Compile the Native Client module and run the application again |
| 437 ====================================================================== |
| 438 |
| 439 Compile the Native Client module by running the '``make``' command again. |
| 440 |
| 441 Run the application by reloading hello_tutorial.html in Chrome. (The page |
| 442 should be at http://localhost:5103/hello_tutorial/hello_tutorial.html assuming |
| 443 the setup described above.) |
| 444 |
| 445 After Chrome loads the Native Client module, you should see an alert panel |
| 446 appear with the message sent from the module. |
| 447 |
| 448 Troubleshooting |
| 449 =============== |
| 450 |
| 451 If your application doesn't run, see :ref:`Step 3 <step_3>` above |
| 452 to verify that you've set up your environment correctly, including both the |
| 453 Chrome browser and the local server. Make sure that you're running a version of |
| 454 Chrome that is equal to or greater than the SDK bundle version you are using, |
| 455 that you've enabled the Native Client flag and relaunched Chrome, that you've |
| 456 disabled the Chrome cache, and that **you're accessing your application from a |
| 457 local web server (rather than by dragging the HTML file into your browser)**. |
| 458 |
| 459 For additional troubleshooting information, check the `FAQ |
| 460 <https://developers.google.com/native-client/faq.html#HangOnLoad>`_. |
| 461 |
| 462 Next steps |
| 463 ========== |
| 464 |
| 465 * See the :doc:`Application Structure <coding/application-structure>` |
| 466 chapter in the Developer's Guide for information about how to structure a |
| 467 Native Client module. |
| 468 * Check the `C++ Reference |
| 469 <https://developers.google.com/native-client/peppercpp>`_ for details about |
| 470 how to use the Pepper APIs. |
| 471 * Browse through the source code of the SDK examples (in the ``examples`` |
| 472 directory) to learn additional techniques for writing Native Client |
| 473 applications and using the Pepper APIs. |
| 474 * See the :doc:`Building <devcycle/building>`, :doc:`Running |
| 475 <devcycle/running>`, and :doc:`Debugging pages <devcycle/debugging>` |
| 476 for information about how to build, run, and debug Native Client |
| 477 applications. |
| 478 * Check the `naclports <http://code.google.com/p/naclports/>`_ project to see |
| 479 what libraries have been ported for use with Native Client. If you port an |
| 480 open-source library for your own use, we recommend adding it to naclports |
| 481 (see `How to check code into naclports |
| 482 <http://code.google.com/p/naclports/wiki/HowTo_Checkin>`_). |
OLD | NEW |