Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / native_client_sdk / src / examples / tutorial / dlopen / dlopen.cc
blob1c643142789f90e660116b751909c1fb686a1543
1 // Copyright (c) 2012 The Chromium 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.
5 #include <dlfcn.h>
6 #include <pthread.h>
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <string.h>
10 #include <sys/mount.h>
12 #include <ppapi/cpp/completion_callback.h>
13 #include <ppapi/cpp/instance.h>
14 #include <ppapi/cpp/module.h>
15 #include <ppapi/cpp/var.h>
17 #include "eightball.h"
18 #include "nacl_io/nacl_io.h"
19 #include "reverse.h"
21 #if defined(NACL_SDK_DEBUG)
22 #define CONFIG_NAME "Debug"
23 #else
24 #define CONFIG_NAME "Release"
25 #endif
27 #if defined __arm__
28 #define NACL_ARCH "arm"
29 #elif defined __i686__
30 #define NACL_ARCH "x86_32"
31 #elif defined __x86_64__
32 #define NACL_ARCH "x86_64"
33 #else
34 #error "Unknown arch"
35 #endif
37 class DlOpenInstance : public pp::Instance {
38 public:
39 explicit DlOpenInstance(PP_Instance instance)
40 : pp::Instance(instance),
41 eightball_so_(NULL),
42 reverse_so_(NULL),
43 eightball_(NULL),
44 reverse_(NULL) {}
46 virtual ~DlOpenInstance() {}
48 // Helper function to post a message back to the JS and stdout functions.
49 void logmsg(const char* pStr) {
50 PostMessage(pp::Var(std::string("log:") + pStr));
51 fprintf(stdout, pStr);
52 fprintf(stdout, "\n");
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 nacl_io_init_ppapi(pp_instance(),
58 pp::Module::Get()->get_browser_interface());
59 // Mount a HTTP mount at /http. All reads from /http/* will read from the
60 // server.
61 mount("", "/http", "httpfs", 0, "");
63 pthread_t thread;
64 logmsg("Spawning thread to cache .so files...");
65 int rtn = pthread_create(&thread, NULL, LoadLibrariesOnWorker, this);
66 if (rtn != 0) {
67 logmsg("ERROR; pthread_create() failed.");
68 return false;
70 rtn = pthread_detach(thread);
71 if (rtn != 0) {
72 logmsg("ERROR; pthread_detach() failed.");
73 return false;
75 return true;
78 // This function is called on a worker thread, and will call dlopen to load
79 // the shared object. In addition, note that this function does NOT call
80 // dlclose, which would close the shared object and unload it from memory.
81 void LoadLibrary() {
82 eightball_so_ = dlopen("libeightball.so", RTLD_LAZY);
83 if (eightball_so_ != NULL) {
84 intptr_t offset = (intptr_t) dlsym(eightball_so_, "Magic8Ball");
85 eightball_ = (TYPE_eightball) offset;
86 if (NULL == eightball_) {
87 std::string message = "dlsym() returned NULL: ";
88 message += dlerror();
89 logmsg(message.c_str());
90 return;
93 logmsg("Loaded libeightball.so");
94 } else {
95 logmsg("libeightball.so did not load");
98 const char reverse_so_path[] =
99 "/http/glibc/" CONFIG_NAME "/libreverse_" NACL_ARCH ".so";
100 reverse_so_ = dlopen(reverse_so_path, RTLD_LAZY);
101 if (reverse_so_ != NULL) {
102 intptr_t offset = (intptr_t) dlsym(reverse_so_, "Reverse");
103 reverse_ = (TYPE_reverse) offset;
104 if (NULL == reverse_) {
105 std::string message = "dlsym() returned NULL: ";
106 message += dlerror();
107 logmsg(message.c_str());
108 return;
110 logmsg("Loaded libreverse.so");
111 } else {
112 logmsg("libreverse.so did not load");
116 // Called by the browser to handle the postMessage() call in Javascript.
117 virtual void HandleMessage(const pp::Var& var_message) {
118 if (!var_message.is_string()) {
119 logmsg("Message is not a string.");
120 return;
123 std::string message = var_message.AsString();
124 if (message == "eightball") {
125 if (NULL == eightball_) {
126 logmsg("Eightball library not loaded");
127 return;
130 std::string ballmessage = "The Magic 8-Ball says: ";
131 ballmessage += eightball_();
132 ballmessage += "!";
134 logmsg(ballmessage.c_str());
135 } else if (message.find("reverse:") == 0) {
136 if (NULL == reverse_) {
137 logmsg("Reverse library not loaded");
138 return;
141 std::string s = message.substr(strlen("reverse:"));
142 char* result = reverse_(s.c_str());
144 std::string message = "Your string reversed: \"";
145 message += result;
146 message += "\"";
148 free(result);
150 logmsg(message.c_str());
151 } else {
152 std::string errormsg = "Unexpected message: ";
153 errormsg += message;
154 logmsg(errormsg.c_str());
158 static void* LoadLibrariesOnWorker(void* pInst) {
159 DlOpenInstance* inst = static_cast<DlOpenInstance*>(pInst);
160 inst->LoadLibrary();
161 return NULL;
164 private:
165 void* eightball_so_;
166 void* reverse_so_;
167 TYPE_eightball eightball_;
168 TYPE_reverse reverse_;
171 class DlOpenModule : public pp::Module {
172 public:
173 DlOpenModule() : pp::Module() {}
174 virtual ~DlOpenModule() {}
176 // Create and return a DlOpenInstance object.
177 virtual pp::Instance* CreateInstance(PP_Instance instance) {
178 return new DlOpenInstance(instance);
182 namespace pp {
183 Module* CreateModule() { return new DlOpenModule(); }
184 } // namespace pp