Chromium Code Reviews| Index: native_client_sdk/src/examples/dlopen/dlopen.cc |
| =================================================================== |
| --- native_client_sdk/src/examples/dlopen/dlopen.cc (revision 0) |
| +++ native_client_sdk/src/examples/dlopen/dlopen.cc (revision 0) |
| @@ -0,0 +1,169 @@ |
| +// Copyright (c) 2012 The Native Client Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +/// @file |
| +/// This example demonstrates building a dynamic library which is loaded by the |
| +/// NaCl module. To load the NaCl module, the browser first looks for the |
| +/// CreateModule() factory method (at the end of this file). It calls |
| +/// CreateModule() once to load the module code from your .nexe. After the |
| +/// .nexe code is loaded, CreateModule() is not called again. |
| +/// |
| +/// Once the .nexe code is loaded, the browser then calls the CreateInstance() |
| +/// method on the object returned by CreateModule(). If the CreateInstance |
| +/// returns successfully, then Init function is called, which will load the |
| +/// shared object on a worker thread. We use a worker because dlopen is |
| +/// a blocking call, which is not alowed on the main thread. |
| + |
| +#include <dlfcn.h> |
| +#include <stdio.h> |
| +#include <stdlib.h> |
| +#include <pthread.h> |
| + |
| +#include <ppapi/cpp/module.h> |
| +#include <ppapi/cpp/completion_callback.h> |
| +#include <ppapi/cpp/var.h> |
| +#include <ppapi/cpp/instance.h> |
| + |
| +#include "eightball.h" |
| + |
| +/// The Instance class. One of these exists for each instance of your NaCl |
| +/// module on the web page. The browser will ask the Module object to create |
| +/// a new Instance for each occurrence of the <embed> tag that has these |
| +/// attributes: |
| +/// <pre> |
| +/// type="application/x-nacl" |
| +/// nacl="dlopen.nmf" |
| +/// </pre> |
| +class dlOpenInstance : public pp::Instance { |
| + public: |
| + explicit dlOpenInstance(pp::Core *core, PP_Instance instance): |
| + pp::Instance(instance) { |
| + _dlhandle = NULL; |
| + _eightball = NULL; |
| + _core = core; |
| + _tid = 0; |
| + }; |
| + virtual ~dlOpenInstance(){}; |
| + |
| + // Helper function to post a message back to the JS and stdout functions. |
| + void logmsg(const char* pStr){ |
| + PostMessage(pp::Var(pStr)); |
| + fprintf(stdout, pStr); |
| + } |
| + |
| + // Initialize the module, staring a worker thread to load the shared object. |
| + virtual bool Init(uint32_t argc, const char* argn[], const char* argv[]){ |
| + logmsg("Spawning thread to cache .so files..."); |
| + if (pthread_create(&_tid, NULL, LoadLibrariesOnWorker, this)) { |
| + logmsg("ERROR; pthread_create() failed.\n"); |
| + return false; |
| + } |
| + return true; |
| + } |
| + |
| + // This function is called on a worker thread, and will call dlopen to load |
| + // the shared object. In addition, note that this function does NOT call |
| + // dlclose, which would close the shared object and unload it from memory. |
| + void LoadLibrary() |
| + { |
| + const int32_t IMMEDIATELY = 0; |
| + _dlhandle = dlopen("libeightball.so", RTLD_LAZY); |
| + pp::CompletionCallback cc(LoadDoneCB, this); |
| + _core->CallOnMainThread(IMMEDIATELY, cc , 0); |
| + } |
| + |
| + // This function will run on the main thread and use the handle it stored by |
| + // the worker thread, assuming it successfully loaded, to get a pointer to the |
| + // message function in the shared object. |
| + void UseLibrary() { |
| + if(this->_dlhandle == NULL){ |
|
Brad Chen
2012/01/31 22:29:54
Google3 style prescribes a space after "if". Miss
noelallen1
2012/02/01 17:46:10
Done.
|
| + logmsg("libeightball.so did not load"); |
| + } |
| + else { |
|
Brad Chen
2012/01/31 22:29:54
I don't particularly care for this formatting and
noelallen1
2012/02/01 17:46:10
Done.
|
| + this->_eightball = (TYPE_eightball) dlsym(this->_dlhandle, "Magic8Ball"); |
| + if (NULL == this->_eightball) { |
| + std::string ballmessage = "dlsym() returned NULL: "; |
| + ballmessage += dlerror(); |
| + ballmessage += "\n"; |
| + logmsg(ballmessage.c_str()); |
| + } |
| + else{ |
| + logmsg("Eightball loaded!"); |
| + } |
| + } |
| + } |
| + |
| + // Called by the browser to handle the postMessage() call in Javascript. |
| + virtual void HandleMessage(const pp::Var& var_message) { |
| + if(NULL == this->_eightball){ |
| + logmsg("Eightball library not loaded"); |
| + return; |
| + } |
| + |
| + if (!var_message.is_string()) { |
| + logmsg("Message is not a string."); |
| + return; |
| + } |
| + |
| + std::string message = var_message.AsString(); |
| + if (message == "query") { |
| + fprintf(stdout, "%s(%d) Got this far.\n", __FILE__, __LINE__); |
| + std::string ballmessage = "!The Magic 8-Ball says: "; |
| + ballmessage += this->_eightball(); |
| + |
| + logmsg(ballmessage.c_str()); |
| + fprintf(stdout, "%s(%d) Got this far.\n", __FILE__, __LINE__); |
| + } |
| + else { |
| + std::string errormsg = "Unexpected message: "; |
| + errormsg += message + "\n"; |
| + logmsg(errormsg.c_str()); |
| + } |
| + } |
| + |
| + static void* LoadLibrariesOnWorker(void *pInst) { |
| + dlOpenInstance *inst = static_cast<dlOpenInstance *>(pInst); |
| + inst->LoadLibrary(); |
| + return NULL; |
| + } |
| + |
| + static void LoadDoneCB(void *pInst, int32_t result) { |
| + dlOpenInstance *inst = static_cast<dlOpenInstance *>(pInst); |
| + inst->UseLibrary(); |
| + } |
| + |
| + private: |
| + void *_dlhandle; |
| + TYPE_eightball _eightball; |
| + pp::Core *_core; |
| + pthread_t _tid; |
| + |
| + }; |
| + |
| +// The Module class. The browser calls the CreateInstance() method to create |
| +// an instance of your NaCl module on the web page. The browser creates a new |
| +// instance for each <embed> tag with type="application/x-nacl". |
| +class dlOpenModule : public pp::Module { |
| + public: |
| + dlOpenModule() : pp::Module() {} |
| + virtual ~dlOpenModule() {} |
| + |
| + // Create and return a dlOpenInstance object. |
| + virtual pp::Instance* CreateInstance(PP_Instance instance) { |
| + return new dlOpenInstance(core(), instance); |
| + } |
| +}; |
| + |
| + |
| +// Factory function called by the browser when the module is first loaded. |
| +// The browser keeps a singleton of this module. It calls the |
| +// CreateInstance() method on the object you return to make instances. There |
| +// is one instance per <embed> tag on the page. This is the main binding |
| +// point for your NaCl module with the browser. |
| +namespace pp { |
| + Module* CreateModule() { |
| + return new dlOpenModule(); |
| + } |
| +} // namespace pp |
| + |
| Property changes on: native_client_sdk/src/examples/dlopen/dlopen.cc |
| ___________________________________________________________________ |
| Added: svn:eol-style |
| + LF |