|
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 |