|
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. | |
Brad Chen
2012/01/28 01:00:52
Where should a developer expect to see an overview
noelallen1
2012/01/31 21:03:21
None of the examples have docs locally. The docs
| |
4 #include <dlfcn.h> // for dlopen | |
5 #include <stdio.h> | |
6 #include <stdlib.h> | |
7 #include <pthread.h> // for pthreads | |
8 | |
9 #include <ppapi/cpp/module.h> | |
10 #include <ppapi/cpp/completion_callback.h> | |
11 #include <ppapi/cpp/var.h> | |
12 #include <ppapi/cpp/instance.h> | |
13 | |
14 #include "eightball.h" | |
15 | |
16 | |
17 // NOTE, dlopen is a BLOCKING call; Behind the scenes, it will kick off an | |
18 // XHR request to dynamically load the .so file from the server, and return | |
Brad Chen
2012/01/28 01:00:52
XHR needs a definition or cross-reference.
noelallen1
2012/01/31 21:03:21
removed
| |
19 // when the .so has been loaded. As such, it cannot be called from the main | |
20 // thread until the .so file has been cached. (otherwise you will stall the | |
Brad Chen
2012/01/28 01:00:52
Not grammatical.
noelallen1
2012/01/31 21:03:21
Done.
| |
21 // process and block indefenitally.) To fix this, you must spin up a temporary | |
22 // thread to call dlopen and dlclose on all of your target .so files before | |
23 // allowing your main thread to query them. | |
24 | |
25 | |
26 // a global handle to the CORE object; this will make it easier to issue | |
Brad Chen
2012/01/28 01:00:52
Especially in external examples I think we should
noelallen1
2012/01/31 21:03:21
Globals removed.
On 2012/01/28 01:00:52, Brad Chen
| |
27 // CallOnMainThread functions w/o API restrictions. | |
28 pp::Core* g_core = NULL; | |
29 | |
30 void* loadLibrariesOnThread(void *pInst); | |
31 | |
32 char *(*eightball)(void); | |
Brad Chen
2012/01/28 01:00:52
The use of indentation and spaces in the above thr
noelallen1
2012/01/31 21:03:21
Done.
| |
33 // the Instance class. | |
Brad Chen
2012/01/28 01:00:52
If this is the first NaCl example a developer look
noelallen1
2012/01/31 21:03:21
Done.
| |
34 class dlOpenInstance : public pp::Instance { | |
Brad Chen
2012/01/28 01:00:52
It sure makes me sad we can't do a simple example
noelallen1
2012/01/31 21:03:21
Done.
| |
35 public: | |
36 explicit dlOpenInstance(PP_Instance instance):pp::Instance(instance) { | |
37 eightball=(NULL); | |
Brad Chen
2012/01/28 01:00:52
" = "
noelallen1
2012/01/31 21:03:21
Done.
| |
38 }; | |
39 virtual ~dlOpenInstance(){}; | |
40 | |
41 // helper function to post a message back to the JS and stdout functions | |
42 void logmsg(const char* pStr){ | |
43 PostMessage(pp::Var(pStr)); | |
44 fprintf(stdout,(const char*)pStr); | |
45 } | |
46 | |
47 | |
48 // this function will run on the main thread and will grab a handle to the | |
49 // .so and it's exposed function. Note that this function is called | |
Brad Chen
2012/01/28 01:00:52
"its" ; also non-standard capitalization. Maybe we
| |
50 // once the library has been loaded properly from a pthread. | |
51 void* loadLibs(void* userData, int32_t result) { | |
52 | |
53 logmsg("calling dlopen() from main thread\n"); | |
Brad Chen
2012/01/28 01:00:52
Why is this not indented? Why the white space befo
| |
54 | |
55 // NOTE, we have not called dlclose on this .so object. Doing so will unload | |
56 // it, and cause this function to go attempt to fetch it again :( | |
57 dlhandle = dlopen("libeightball.so", RTLD_LAZY); | |
58 if(dlhandle == NULL){ | |
Brad Chen
2012/01/28 01:00:52
"if (dlhandle == NULL) {"
I really think we need t
noelallen1
2012/01/31 21:03:21
Done.
| |
59 logmsg("libeightball.so did not load"); | |
60 return false; | |
61 } | |
62 else { | |
63 eightball = (TYPE_eightball) dlsym(dlhandle, "Magic8Ball"); | |
64 if (eightball == NULL) { | |
65 std::string ballmessage; | |
66 sprintf(&ballmessage[0], "dlsym() returned NULL : %s\n",dlerror()); | |
67 logmsg(ballmessage.c_str()); | |
68 return false; | |
69 } | |
70 else{ | |
71 logmsg("Eightball loaded!"); | |
72 } | |
73 } | |
74 | |
75 return 0; | |
76 } | |
77 | |
78 // Init the module | |
79 virtual bool Init(uint32_t argc, const char* argn[], const char* argv[]){ | |
80 // spawn a thread to load up our .so objects | |
81 pthread_t threadHdl; | |
82 logmsg("Spawning thread to cache .so files..."); | |
83 int rc = pthread_create(&threadHdl, NULL, loadLibrariesOnThread, NULL); | |
84 if (rc){ | |
85 logmsg("ERROR; return code from pthread_create()\n"); | |
86 return false; | |
87 } | |
88 | |
89 return true; | |
90 } | |
91 | |
92 // Called by the browser to handle the postMessage() call in Javascript. | |
93 virtual void HandleMessage(const pp::Var& var_message) { | |
94 if(eightball == NULL){ | |
95 logmsg("Eightball library not loaded"); | |
96 } | |
97 else if (!var_message.is_string()) { | |
98 logmsg("Unknown"); | |
99 } | |
100 else{ | |
101 std::string message = var_message.AsString(); | |
102 if (message == "query") { | |
103 std::string ballmessage; | |
104 sprintf(&ballmessage[0], "!The Magic 8-Ball says: %s", eightball()); | |
105 logmsg(ballmessage.c_str()); | |
106 } | |
107 } | |
108 } | |
109 private: | |
110 void *dlhandle; | |
111 | |
112 }; | |
113 | |
114 // A global instance of the dlOpenInstance object; This will make the callbacks easier | |
Brad Chen
2012/01/28 01:00:52
long line, grammar, punctuation, capitalization et
| |
115 // from the pthread doing the loading of dlobjects. | |
116 dlOpenInstance* gInstance; | |
117 | |
118 // The Module class. The browser calls the CreateInstance() method to create | |
119 // an instance of your NaCl module on the web page. The browser creates a new | |
120 // instance for each <embed> tag with type="application/x-nacl". | |
121 class dlOpenModule : public pp::Module { | |
122 public: | |
123 dlOpenModule() : pp::Module() {} | |
124 virtual ~dlOpenModule() {} | |
125 | |
126 // Create and return a dlOpenInstance object. | |
127 virtual pp::Instance* CreateInstance(PP_Instance instance) { | |
128 g_core = core(); | |
129 gInstance= new dlOpenInstance(instance); | |
130 return gInstance; | |
131 } | |
132 }; | |
133 | |
134 // this callback is here simply to help us call the static instance. | |
135 // We can't pass pointers to members in g++ so this is the fix. | |
136 void libLoaderCBHelper(void* userData, int32_t result){ | |
137 gInstance->loadLibs(userData,result); | |
138 } | |
139 | |
140 | |
141 // this function is called on a worker thread, and will call dlopen to load the | |
142 // object remember, dlopen is a blocking call, and thus, cannot be called on | |
143 // the main thread in addition, note that this function does NOT call dlclose; | |
144 // That would close the shared object and unload it from memory, such that | |
145 // subisquent dlopens would attempt to re-load them from cache / network. | |
146 void* loadLibrariesOnThread(void *pInst) | |
147 { | |
148 | |
Brad Chen
2012/01/28 01:00:52
Please get rid of the extra whitespace.
| |
149 const int err=-27; | |
150 void* dlhandle = dlopen("libeightball.so", RTLD_LAZY); | |
151 if(dlhandle == NULL) | |
152 pthread_exit((void*)&err); | |
153 | |
154 | |
155 // issue a callback on the main thread to load the libraries there. | |
156 pp::CompletionCallback cc(libLoaderCBHelper, 0); | |
157 g_core->CallOnMainThread(0, cc , 0); | |
Brad Chen
2012/01/28 01:00:52
What do you actually need to do on the main thread
| |
158 | |
159 pthread_exit(NULL); | |
160 } | |
161 | |
162 | |
163 | |
164 // Factory function called by the browser when the module is first loaded. | |
165 // The browser keeps a singleton of this module. It calls the | |
166 // CreateInstance() method on the object you return to make instances. There | |
167 // is one instance per <embed> tag on the page. This is the main binding | |
168 // point for your NaCl module with the browser. | |
169 namespace pp { | |
170 Module* CreateModule() { | |
171 return new dlOpenModule(); | |
172 } | |
173 } // namespace pp | |
174 | |
OLD | NEW |