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,174 @@ |
+// 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. |
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
|
+#include <dlfcn.h> // for dlopen |
+#include <stdio.h> |
+#include <stdlib.h> |
+#include <pthread.h> // for pthreads |
+ |
+#include <ppapi/cpp/module.h> |
+#include <ppapi/cpp/completion_callback.h> |
+#include <ppapi/cpp/var.h> |
+#include <ppapi/cpp/instance.h> |
+ |
+#include "eightball.h" |
+ |
+ |
+// NOTE, dlopen is a BLOCKING call; Behind the scenes, it will kick off an |
+// 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
|
+// when the .so has been loaded. As such, it cannot be called from the main |
+// 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.
|
+// process and block indefenitally.) To fix this, you must spin up a temporary |
+// thread to call dlopen and dlclose on all of your target .so files before |
+// allowing your main thread to query them. |
+ |
+ |
+// 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
|
+// CallOnMainThread functions w/o API restrictions. |
+pp::Core* g_core = NULL; |
+ |
+void* loadLibrariesOnThread(void *pInst); |
+ |
+ 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.
|
+// 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.
|
+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.
|
+ public: |
+ explicit dlOpenInstance(PP_Instance instance):pp::Instance(instance) { |
+ eightball=(NULL); |
Brad Chen
2012/01/28 01:00:52
" = "
noelallen1
2012/01/31 21:03:21
Done.
|
+ }; |
+ 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,(const char*)pStr); |
+ } |
+ |
+ |
+ // this function will run on the main thread and will grab a handle to the |
+ // .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
|
+ // once the library has been loaded properly from a pthread. |
+ void* loadLibs(void* userData, int32_t result) { |
+ |
+ 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
|
+ |
+ // NOTE, we have not called dlclose on this .so object. Doing so will unload |
+ // it, and cause this function to go attempt to fetch it again :( |
+ dlhandle = dlopen("libeightball.so", RTLD_LAZY); |
+ 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.
|
+ logmsg("libeightball.so did not load"); |
+ return false; |
+ } |
+ else { |
+ eightball = (TYPE_eightball) dlsym(dlhandle, "Magic8Ball"); |
+ if (eightball == NULL) { |
+ std::string ballmessage; |
+ sprintf(&ballmessage[0], "dlsym() returned NULL : %s\n",dlerror()); |
+ logmsg(ballmessage.c_str()); |
+ return false; |
+ } |
+ else{ |
+ logmsg("Eightball loaded!"); |
+ } |
+ } |
+ |
+ return 0; |
+ } |
+ |
+ // Init the module |
+ virtual bool Init(uint32_t argc, const char* argn[], const char* argv[]){ |
+ // spawn a thread to load up our .so objects |
+ pthread_t threadHdl; |
+ logmsg("Spawning thread to cache .so files..."); |
+ int rc = pthread_create(&threadHdl, NULL, loadLibrariesOnThread, NULL); |
+ if (rc){ |
+ logmsg("ERROR; return code from pthread_create()\n"); |
+ return false; |
+ } |
+ |
+ return true; |
+ } |
+ |
+ // Called by the browser to handle the postMessage() call in Javascript. |
+ virtual void HandleMessage(const pp::Var& var_message) { |
+ if(eightball == NULL){ |
+ logmsg("Eightball library not loaded"); |
+ } |
+ else if (!var_message.is_string()) { |
+ logmsg("Unknown"); |
+ } |
+ else{ |
+ std::string message = var_message.AsString(); |
+ if (message == "query") { |
+ std::string ballmessage; |
+ sprintf(&ballmessage[0], "!The Magic 8-Ball says: %s", eightball()); |
+ logmsg(ballmessage.c_str()); |
+ } |
+ } |
+ } |
+ private: |
+ void *dlhandle; |
+ |
+ }; |
+ |
+// 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
|
+// from the pthread doing the loading of dlobjects. |
+dlOpenInstance* gInstance; |
+ |
+// 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) { |
+ g_core = core(); |
+ gInstance= new dlOpenInstance(instance); |
+ return gInstance; |
+ } |
+}; |
+ |
+// this callback is here simply to help us call the static instance. |
+// We can't pass pointers to members in g++ so this is the fix. |
+void libLoaderCBHelper(void* userData, int32_t result){ |
+ gInstance->loadLibs(userData,result); |
+} |
+ |
+ |
+// this function is called on a worker thread, and will call dlopen to load the |
+// object remember, dlopen is a blocking call, and thus, cannot be called on |
+// the main thread in addition, note that this function does NOT call dlclose; |
+// That would close the shared object and unload it from memory, such that |
+// subisquent dlopens would attempt to re-load them from cache / network. |
+void* loadLibrariesOnThread(void *pInst) |
+{ |
+ |
Brad Chen
2012/01/28 01:00:52
Please get rid of the extra whitespace.
|
+ const int err=-27; |
+ void* dlhandle = dlopen("libeightball.so", RTLD_LAZY); |
+ if(dlhandle == NULL) |
+ pthread_exit((void*)&err); |
+ |
+ |
+ // issue a callback on the main thread to load the libraries there. |
+ pp::CompletionCallback cc(libLoaderCBHelper, 0); |
+ 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
|
+ |
+ pthread_exit(NULL); |
+} |
+ |
+ |
+ |
+// 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 |