Native Client

C++ Tutorial: Getting Started

Basics

This tutorial shows you how to create, compile, and run a Native Client web application. The Native Client module you will create as part of the web app will be written in C++.

A Native Client web app consists of at least three entities:

  • The HTML web page (*.html). The page can also contain JavaScript code and CSS styles, or the scripting and styling code can go in separate .js and .css files.
  • A Native Client module, written in C or C++. Native Client modules uses the Pepper API, included in the SDK, as a bridge between the browser and the modules. When compiled, the extension for a Native Client module is .nexe.
  • A manifest file (*.nmf) that is used by the browser to determine which compiled Native Client module to load for a given end-user instruction set ("x86-64" or "x86-32").

What the app in this tutorial does

This example shows how to load a Native Client module from a web page and how to send messages between JavaScript and the Native Client module. In this simple app, the JavaScript in the web page sends a "hello" message to the Native Client module. When the Native Client module receives a message, it checks whether the message is equal to the string "hello." If it is, the Native Client module returns a message saying "hello from NaCl." A JavaScript alert displays the message received from the Native Client module.

This tutorial uses a Python script to create a set of template files that you can use as a starting point. The template code shows how to set up a simple message handler on the Native Client side. It also provides boilerplate code in the HTML file for adding an event listener to the web page to receive messages from the Native Client module.

Communication between JavaScript and a Native Client module

Communication between JavaScript code in the browser and C++ code in a Native Client module is two-way: the browser can send messages to the Native Client module. The Native Client module can respond to the message from JavaScript, or it can initiate its own message to JavaScript. In all cases, the communication is asynchronous. A message is sent, but the system does not wait for a response. This behavior is analogous to client/server web communication, where the client posts a message to the server and returns immediately.

Step 1: Download and install the Native Client SDK and Python.

Follow the instructions on the Download page to download and install the Native Client SDK.

Step 2: Download and install Python if necessary.

A number of tools in the SDK (including the SCons build tool) require Python to run. Python is typically included on Mac and Linux systems, but not on Windows systems. To check whether you have Python installed on your system, enter the python command on the command line; you should get the interactive Python prompt (>>>).

If you need to install Python, you can get it here: http://www.python.org/download/. Select the latest 2.x version. Be sure to add the Python directory (for example, C:\python27 on Windows) to the PATH variable.

Step 3: Start a local server.

To protect against security vulnerabilities, you must load Native Client modules from a web server (either remote or local). Simply dragging and dropping Native Client files into the browser address bar will not work. For more information, read about the Same Origin Policy, which protects the user's file system from outside access.

The Native Client SDK includes a simple Python web server that you can use to run apps that you build (including the app in this tutorial). To start the web server, go to the examples/ directory in the SDK and run the command below:

cd examples
python httpd.py 5103

After you start the local server you can access it at http://localhost:5103.

Of course, you don't have to use the server included in the SDK – any web server will do. If you prefer to use another web server already installed on your system, that's fine.

Step 4: Set up Chrome and verify that Native Client is working.

Set up Chrome as follows:

  • Make sure you are using Google Chrome version 14 or greater.
  • If you haven't already done so, enable the Native Client flag in Google Chrome. Type about:flags in the Chrome address bar, scroll down to "Native Client," click the "Enable" link, scroll down to the bottom of the page, and click the "Relaunch Now" button (all browser windows will restart).
  • Verify that the Native Client plugin is enabled in Google Chrome. Type about:plugins in the Chrome address bar, scroll down to "Native Client", and click the "Enable" link if the plugin is not already enabled. (You do not need to relaunch Chrome after you enable the Native Client plugin.)

After you've set up Chrome, you can verify that everything is working properly as follows:

  • First, make sure you can run the examples in the SDK Examples.
  • Then run the examples in the SDK from your local server. If you started the local server as described in Step 3, go to http://localhost:5103/ and you'll see a page with links to each of the pre-built SDK examples. Click on one or two of the links and run the examples.

Step 5: Create a set of template files for your project.

The SDK includes a Python script, init_project.py, that sets up a simple Native Client project using the name and language (C++ or C) you specify.

The script creates the following template files in the directory you specify:

  • your_project_name.html, the web page that loads the Native Client module
  • your_project_name.cc (or .c), source code for the Native Client module
  • scons (or scons.bat), a driver script that runs the SCons tool to build your application
  • build.scons, the build instructions for your application

The script has the following command line options:

  • -n your project name (use lowercase letters with underscores and numbers but no uppercase letters)
  • -d directory for your project
  • -c create project using C (C++ is the default). Include the -c option if you want to write a Native Client module in C.

To create a C++ project named hello_tutorial in the examples/ directory, go to the project_templates/ directory and run the script with the following options:

cd project_templates
python init_project.py -d ../examples -n hello_tutorial 

This step creates the directory examples/hello_tutorial with the following files:

  • build.scons
  • hello_tutorial.html
  • hello_tutorial.cc
  • scons

In this tutorial, you're adding your project to the examples/ directory because that's where the local server runs, ready to serve your new project. You can place your project directory anywhere on the filesystem, as long as that location is being served by your server.

Step 6: Modify the web page to load and communicate with the Native Client module.

Next, you'll modify the hello_tutorial.html and hello_tutorial.cc files. When your web page (hello_tutorial.html) is loaded into the browser, the compiled Native Client module (hello_tutorial.nexe) will be loaded and run. In this step, you'll modify the moduleDidLoad() JavaScript function to send a "hello" message to the Native Client module.

The template files supplied here contain boilerplate code that is used in most Native Client web apps. You'll find these files a useful starting point for future experimentation with other features of the Native Client SDK.

The <embed> element (toward the end of hello_tutorial.html) is where the Native Client module is loaded. The init_project.py script has already filled in the ID attribute of your module as well as the name of the associated manifest file:

<embed name="nacl_module"
       id="hello_tutorial"
       width=0 height=0
       src="hello_tutorial.nmf"
       type="application/x-nacl" />

The manifest file is described in Step 8 below.

The <embed> element is wrapped inside a <div> element with a load event listener that fires when the Native Client module successfully loads.

At the end of the moduleDidLoad() function, add the new code below (indicated by boldface type) to send a message to the Native Client module:

function moduleDidLoad() {
      HelloTutorialModule = document.getElementById('hello_tutorial');
      HelloTutorialModule.addEventListener('message', handleMessage, false);
      updateStatus('SUCCESS');
      //Send a message to the NaCl module.
      HelloTutorialModule.postMessage('hello');
}

Note that the boilerplate code in this function also adds an event listener for messages received from the Native Client module. The boilerplate handleMessage() function simply prints an alert displaying the data contained in the message event.

Step 7: Implement a message handler in the Native Client module.

In this step, you modify the Native Client module (hello_tutorial.cc) to do the following:

Add the code to define the variables used by the Native Client methods (the "hello" string you're expecting to receive from JavaScript and the reply string you want to return to JavaScript as a response). Add this code to the .cc file after the #include statements:

namespace {
// The expected string sent by the browser.
const char* const kHelloString = "hello";
// The string sent back to the browser upon receipt of a message
// containing "hello".
const char* const kReplyString = "hello from NaCl";
} // namespace

Now, implement the HandleMessage() method to check for kHelloString and return kReplyString. Look for the following line:

// TODO(sdk_user): 1. Make this function handle the incoming message.

and add these lines to the HandleMessage() method:

virtual void HandleMessage(const pp::Var& var_message) {  
  if (!var_message.is_string())
    return;
  std::string message = var_message.AsString();
  pp::Var var_reply;
  if (message == kHelloString) {
    var_reply = pp::Var(kReplyString);
    PostMessage(var_reply);
  }
}

Step 8: Compile the Native Client module.

To compile the Native Client module (hello_tutorial.cc), be sure you are still in the examples/hello_tutorial/ directory and then run the scons script (or scons.bat on Windows). For example:

cd examples/hello_tutorial
./scons

The scons script produces executable Native Client modules for both x86_32 and x86_64 architectures:

  • hello_tutorial_x86_32.nexe
  • hello_tutorial_x86_32_dbg.nexe
  • hello_tutorial_x86_64.nexe
  • hello_tutorial_x86_64_dbg.nexe

The "dbg" .nexes retain symbol information that you can when debugging your module.

In addition to building the .nexe modules, the scons script also generates a manifest file for your application. Manifest files include a set of key-value pairs that tell the browser which .nexe module to load based on the end user's processor architecture. The manifest file for this tutorial, hello_tutorial.nmf, looks as follows:

{
  "program": {
    "x86-64": {"url": "hello_tutorial_x86_64.nexe"},
    "x86-32": {"url": "hello_tutorial_x86_32.nexe"}
  }
}

Step 9: Try it out.

Load the hello_tutorial.html web page into the Chrome browser by visiting the following URL: http://localhost:5103/hello_tutorial/hello_tutorial.html.

After Chrome loads the Native Client module, an alert appears with the message from the module.

When you make changes to your program and want to reload the web page to view your changes, be sure to clear the cache so that the new version is loaded. (From the toolbar menu, click the wrench icon, then select Preferences (or Options) > Under the Hood > Clear browsing data.) Optionally, you can run in Incognito mode and use Shift-Refresh to reload the page.

Troubleshooting

If your application doesn't run, see Step 4 above to verify that you've set up your environment correctly, including both the browser and the server. Make sure that you're running Chrome 14 or greater, that you've enabled both the Native Client flag and plugin and relaunched Chrome, and that you're accessing your application from a local web server (rather than by dragging the HTML file into your browser).

For additional troubleshooting information, check the FAQ.

Next steps

  • See the Application Structure chapter and the C++ Reference for details on how to structure your NaCl modules and use the Pepper APIs.
  • See the source code for each of the Native Client SDK examples (in the examples/ directory) to learn additional techniques for writing web applications and using the Pepper APIs.
  • See the Compiling page for information on how to modify SCons build files and how to debug and test your NaCl modules.
  • Check the naclports project to see what libraries have been ported for use with Native Client. If you port an open-source library for your own use, we recommend adding it to naclports (see How to check code into naclports).

Authentication required

You need to be signed in with Google+ to do that.

Signing you in...

Google Developers needs your permission to do that.