Chromium Code Reviews
|
| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright (c) 2012 The Native Client Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 /// @file | |
| 6 /// This example demonstrates building a dynamic library which is loaded by the | |
| 7 /// NaCl module. To load the NaCl module, the browser first looks for the | |
| 8 /// CreateModule() factory method (at the end of this file). It calls | |
| 9 /// CreateModule() once to load the module code from your .nexe. After the | |
| 10 /// .nexe code is loaded, CreateModule() is not called again. | |
| 11 /// | |
| 12 /// Once the .nexe code is loaded, the browser then calls the CreateInstance() | |
| 13 /// method on the object returned by CreateModule(). If the CreateInstance | |
| 14 /// returns successfully, then Init function is called, which will load the | |
| 15 /// shared object on a worker thread. We use a worker because dlopen is | |
| 16 /// a blocking call, which is not alowed on the main thread. | |
| 17 | |
| 18 #include <dlfcn.h> | |
| 19 #include <stdio.h> | |
| 20 #include <stdlib.h> | |
| 21 #include <pthread.h> | |
| 22 | |
| 23 #include <ppapi/cpp/module.h> | |
| 24 #include <ppapi/cpp/completion_callback.h> | |
| 25 #include <ppapi/cpp/var.h> | |
| 26 #include <ppapi/cpp/instance.h> | |
| 27 | |
| 28 #include "eightball.h" | |
| 29 | |
| 30 /// The Instance class. One of these exists for each instance of your NaCl | |
| 31 /// module on the web page. The browser will ask the Module object to create | |
| 32 /// a new Instance for each occurrence of the <embed> tag that has these | |
| 33 /// attributes: | |
| 34 /// <pre> | |
| 35 /// type="application/x-nacl" | |
| 36 /// nacl="dlopen.nmf" | |
| 37 /// </pre> | |
| 38 class dlOpenInstance : public pp::Instance { | |
| 39 public: | |
| 40 explicit dlOpenInstance(pp::Core *core, PP_Instance instance): | |
| 41 pp::Instance(instance) { | |
| 42 _dlhandle = NULL; | |
| 43 _eightball = NULL; | |
| 44 _core = core; | |
| 45 _tid = 0; | |
| 46 }; | |
| 47 virtual ~dlOpenInstance(){}; | |
| 48 | |
| 49 // Helper function to post a message back to the JS and stdout functions. | |
| 50 void logmsg(const char* pStr){ | |
| 51 PostMessage(pp::Var(pStr)); | |
| 52 fprintf(stdout, pStr); | |
| 53 } | |
| 54 | |
| 55 // Initialize the module, staring a worker thread to load the shared object. | |
| 56 virtual bool Init(uint32_t argc, const char* argn[], const char* argv[]){ | |
| 57 logmsg("Spawning thread to cache .so files..."); | |
| 58 if (pthread_create(&_tid, NULL, LoadLibrariesOnWorker, this)) { | |
| 59 logmsg("ERROR; pthread_create() failed.\n"); | |
| 60 return false; | |
| 61 } | |
| 62 return true; | |
| 63 } | |
| 64 | |
| 65 // This function is called on a worker thread, and will call dlopen to load | |
| 66 // the shared object. In addition, note that this function does NOT call | |
| 67 // dlclose, which would close the shared object and unload it from memory. | |
| 68 void LoadLibrary() | |
| 69 { | |
| 70 const int32_t IMMEDIATELY = 0; | |
| 71 _dlhandle = dlopen("libeightball.so", RTLD_LAZY); | |
| 72 pp::CompletionCallback cc(LoadDoneCB, this); | |
| 73 _core->CallOnMainThread(IMMEDIATELY, cc , 0); | |
| 74 } | |
| 75 | |
| 76 // This function will run on the main thread and use the handle it stored by | |
| 77 // the worker thread, assuming it successfully loaded, to get a pointer to the | |
| 78 // message function in the shared object. | |
| 79 void UseLibrary() { | |
| 80 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.
| |
| 81 logmsg("libeightball.so did not load"); | |
| 82 } | |
| 83 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.
| |
| 84 this->_eightball = (TYPE_eightball) dlsym(this->_dlhandle, "Magic8Ball"); | |
| 85 if (NULL == this->_eightball) { | |
| 86 std::string ballmessage = "dlsym() returned NULL: "; | |
| 87 ballmessage += dlerror(); | |
| 88 ballmessage += "\n"; | |
| 89 logmsg(ballmessage.c_str()); | |
| 90 } | |
| 91 else{ | |
| 92 logmsg("Eightball loaded!"); | |
| 93 } | |
| 94 } | |
| 95 } | |
| 96 | |
| 97 // Called by the browser to handle the postMessage() call in Javascript. | |
| 98 virtual void HandleMessage(const pp::Var& var_message) { | |
| 99 if(NULL == this->_eightball){ | |
| 100 logmsg("Eightball library not loaded"); | |
| 101 return; | |
| 102 } | |
| 103 | |
| 104 if (!var_message.is_string()) { | |
| 105 logmsg("Message is not a string."); | |
| 106 return; | |
| 107 } | |
| 108 | |
| 109 std::string message = var_message.AsString(); | |
| 110 if (message == "query") { | |
| 111 fprintf(stdout, "%s(%d) Got this far.\n", __FILE__, __LINE__); | |
| 112 std::string ballmessage = "!The Magic 8-Ball says: "; | |
| 113 ballmessage += this->_eightball(); | |
| 114 | |
| 115 logmsg(ballmessage.c_str()); | |
| 116 fprintf(stdout, "%s(%d) Got this far.\n", __FILE__, __LINE__); | |
| 117 } | |
| 118 else { | |
| 119 std::string errormsg = "Unexpected message: "; | |
| 120 errormsg += message + "\n"; | |
| 121 logmsg(errormsg.c_str()); | |
| 122 } | |
| 123 } | |
| 124 | |
| 125 static void* LoadLibrariesOnWorker(void *pInst) { | |
| 126 dlOpenInstance *inst = static_cast<dlOpenInstance *>(pInst); | |
| 127 inst->LoadLibrary(); | |
| 128 return NULL; | |
| 129 } | |
| 130 | |
| 131 static void LoadDoneCB(void *pInst, int32_t result) { | |
| 132 dlOpenInstance *inst = static_cast<dlOpenInstance *>(pInst); | |
| 133 inst->UseLibrary(); | |
| 134 } | |
| 135 | |
| 136 private: | |
| 137 void *_dlhandle; | |
| 138 TYPE_eightball _eightball; | |
| 139 pp::Core *_core; | |
| 140 pthread_t _tid; | |
| 141 | |
| 142 }; | |
| 143 | |
| 144 // The Module class. The browser calls the CreateInstance() method to create | |
| 145 // an instance of your NaCl module on the web page. The browser creates a new | |
| 146 // instance for each <embed> tag with type="application/x-nacl". | |
| 147 class dlOpenModule : public pp::Module { | |
| 148 public: | |
| 149 dlOpenModule() : pp::Module() {} | |
| 150 virtual ~dlOpenModule() {} | |
| 151 | |
| 152 // Create and return a dlOpenInstance object. | |
| 153 virtual pp::Instance* CreateInstance(PP_Instance instance) { | |
| 154 return new dlOpenInstance(core(), instance); | |
| 155 } | |
| 156 }; | |
| 157 | |
| 158 | |
| 159 // Factory function called by the browser when the module is first loaded. | |
| 160 // The browser keeps a singleton of this module. It calls the | |
| 161 // CreateInstance() method on the object you return to make instances. There | |
| 162 // is one instance per <embed> tag on the page. This is the main binding | |
| 163 // point for your NaCl module with the browser. | |
| 164 namespace pp { | |
| 165 Module* CreateModule() { | |
| 166 return new dlOpenModule(); | |
| 167 } | |
| 168 } // namespace pp | |
| 169 | |
| OLD | NEW |