- add sources.
[platform/framework/web/crosswalk.git] / src / native_client_sdk / src / examples / tutorial / dlopen / dlopen.cc
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.
4
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>
11
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>
16
17 #include "eightball.h"
18 #include "nacl_io/nacl_io.h"
19 #include "reverse.h"
20
21 #if defined(NACL_SDK_DEBUG)
22 #define CONFIG_NAME "Debug"
23 #else
24 #define CONFIG_NAME "Release"
25 #endif
26
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
36
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),
45         tid_(NULL) {}
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(std::string("log:") + pStr));
52     fprintf(stdout, pStr);
53     fprintf(stdout, "\n");
54   }
55
56   // Initialize the module, staring a worker thread to load the shared object.
57   virtual bool Init(uint32_t argc, const char* argn[], const char* argv[]) {
58     nacl_io_init_ppapi(pp_instance(),
59                        pp::Module::Get()->get_browser_interface());
60     // Mount a HTTP mount at /http. All reads from /http/* will read from the
61     // server.
62     mount("", "/http", "httpfs", 0, "");
63
64     logmsg("Spawning thread to cache .so files...");
65     if (pthread_create(&tid_, NULL, LoadLibrariesOnWorker, this)) {
66       logmsg("ERROR; pthread_create() failed.");
67       return false;
68     }
69     return true;
70   }
71
72   // This function is called on a worker thread, and will call dlopen to load
73   // the shared object.  In addition, note that this function does NOT call
74   // dlclose, which would close the shared object and unload it from memory.
75   void LoadLibrary() {
76     eightball_so_ = dlopen("libeightball.so", RTLD_LAZY);
77     if (eightball_so_ != NULL) {
78       intptr_t offset = (intptr_t) dlsym(eightball_so_, "Magic8Ball");
79       eightball_ = (TYPE_eightball) offset;
80       if (NULL == eightball_) {
81         std::string message = "dlsym() returned NULL: ";
82         message += dlerror();
83         logmsg(message.c_str());
84         return;
85       }
86
87       logmsg("Loaded libeightball.so");
88     } else {
89       logmsg("libeightball.so did not load");
90     }
91
92     const char reverse_so_path[] =
93         "/http/glibc/" CONFIG_NAME "/libreverse_" NACL_ARCH ".so";
94     reverse_so_ = dlopen(reverse_so_path, RTLD_LAZY);
95     if (reverse_so_ != NULL) {
96       intptr_t offset = (intptr_t) dlsym(reverse_so_, "Reverse");
97       reverse_ = (TYPE_reverse) offset;
98       if (NULL == reverse_) {
99         std::string message = "dlsym() returned NULL: ";
100         message += dlerror();
101         logmsg(message.c_str());
102         return;
103       }
104       logmsg("Loaded libreverse.so");
105     } else {
106       logmsg("libreverse.so did not load");
107     }
108   }
109
110   // Called by the browser to handle the postMessage() call in Javascript.
111   virtual void HandleMessage(const pp::Var& var_message) {
112     if (!var_message.is_string()) {
113       logmsg("Message is not a string.");
114       return;
115     }
116
117     std::string message = var_message.AsString();
118     if (message == "eightball") {
119       if (NULL == eightball_) {
120         logmsg("Eightball library not loaded");
121         return;
122       }
123
124       std::string ballmessage = "The Magic 8-Ball says: ";
125       ballmessage += eightball_();
126       ballmessage += "!";
127
128       logmsg(ballmessage.c_str());
129     } else if (message.find("reverse:") == 0) {
130       if (NULL == reverse_) {
131         logmsg("Reverse library not loaded");
132         return;
133       }
134
135       std::string s = message.substr(strlen("reverse:"));
136       char* result = reverse_(s.c_str());
137
138       std::string message = "Your string reversed: \"";
139       message += result;
140       message += "\"";
141
142       free(result);
143
144       logmsg(message.c_str());
145     } else {
146       std::string errormsg = "Unexpected message: ";
147       errormsg += message;
148       logmsg(errormsg.c_str());
149     }
150   }
151
152   static void* LoadLibrariesOnWorker(void* pInst) {
153     DlOpenInstance* inst = static_cast<DlOpenInstance*>(pInst);
154     inst->LoadLibrary();
155     return NULL;
156   }
157
158  private:
159   void* eightball_so_;
160   void* reverse_so_;
161   TYPE_eightball eightball_;
162   TYPE_reverse reverse_;
163   pthread_t tid_;
164 };
165
166 class DlOpenModule : public pp::Module {
167  public:
168   DlOpenModule() : pp::Module() {}
169   virtual ~DlOpenModule() {}
170
171   // Create and return a DlOpenInstance object.
172   virtual pp::Instance* CreateInstance(PP_Instance instance) {
173     return new DlOpenInstance(instance);
174   }
175 };
176
177 namespace pp {
178 Module* CreateModule() { return new DlOpenModule(); }
179 }  // namespace pp