Home | History | Annotate | Download | only in tutorial
      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