root/native_client_sdk/src/examples/tutorial/dlopen/dlopen.cc

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. tid_
  2. logmsg
  3. Init
  4. LoadLibrary
  5. HandleMessage
  6. LoadLibrariesOnWorker
  7. CreateInstance
  8. CreateModule

// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <dlfcn.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mount.h>

#include <ppapi/cpp/completion_callback.h>
#include <ppapi/cpp/instance.h>
#include <ppapi/cpp/module.h>
#include <ppapi/cpp/var.h>

#include "eightball.h"
#include "nacl_io/nacl_io.h"
#include "reverse.h"

#if defined(NACL_SDK_DEBUG)
#define CONFIG_NAME "Debug"
#else
#define CONFIG_NAME "Release"
#endif

#if defined __arm__
#define NACL_ARCH "arm"
#elif defined __i686__
#define NACL_ARCH "x86_32"
#elif defined __x86_64__
#define NACL_ARCH "x86_64"
#else
#error "Unknown arch"
#endif

class DlOpenInstance : public pp::Instance {
 public:
  explicit DlOpenInstance(PP_Instance instance)
      : pp::Instance(instance),
        eightball_so_(NULL),
        reverse_so_(NULL),
        eightball_(NULL),
        reverse_(NULL),
        tid_(NULL) {}

  virtual ~DlOpenInstance() {}

  // Helper function to post a message back to the JS and stdout functions.
  void logmsg(const char* pStr) {
    PostMessage(pp::Var(std::string("log:") + pStr));
    fprintf(stdout, pStr);
    fprintf(stdout, "\n");
  }

  // Initialize the module, staring a worker thread to load the shared object.
  virtual bool Init(uint32_t argc, const char* argn[], const char* argv[]) {
    nacl_io_init_ppapi(pp_instance(),
                       pp::Module::Get()->get_browser_interface());
    // Mount a HTTP mount at /http. All reads from /http/* will read from the
    // server.
    mount("", "/http", "httpfs", 0, "");

    logmsg("Spawning thread to cache .so files...");
    if (pthread_create(&tid_, NULL, LoadLibrariesOnWorker, this)) {
      logmsg("ERROR; pthread_create() failed.");
      return false;
    }
    return true;
  }

  // This function is called on a worker thread, and will call dlopen to load
  // the shared object.  In addition, note that this function does NOT call
  // dlclose, which would close the shared object and unload it from memory.
  void LoadLibrary() {
    eightball_so_ = dlopen("libeightball.so", RTLD_LAZY);
    if (eightball_so_ != NULL) {
      intptr_t offset = (intptr_t) dlsym(eightball_so_, "Magic8Ball");
      eightball_ = (TYPE_eightball) offset;
      if (NULL == eightball_) {
        std::string message = "dlsym() returned NULL: ";
        message += dlerror();
        logmsg(message.c_str());
        return;
      }

      logmsg("Loaded libeightball.so");
    } else {
      logmsg("libeightball.so did not load");
    }

    const char reverse_so_path[] =
        "/http/glibc/" CONFIG_NAME "/libreverse_" NACL_ARCH ".so";
    reverse_so_ = dlopen(reverse_so_path, RTLD_LAZY);
    if (reverse_so_ != NULL) {
      intptr_t offset = (intptr_t) dlsym(reverse_so_, "Reverse");
      reverse_ = (TYPE_reverse) offset;
      if (NULL == reverse_) {
        std::string message = "dlsym() returned NULL: ";
        message += dlerror();
        logmsg(message.c_str());
        return;
      }
      logmsg("Loaded libreverse.so");
    } else {
      logmsg("libreverse.so did not load");
    }
  }

  // Called by the browser to handle the postMessage() call in Javascript.
  virtual void HandleMessage(const pp::Var& var_message) {
    if (!var_message.is_string()) {
      logmsg("Message is not a string.");
      return;
    }

    std::string message = var_message.AsString();
    if (message == "eightball") {
      if (NULL == eightball_) {
        logmsg("Eightball library not loaded");
        return;
      }

      std::string ballmessage = "The Magic 8-Ball says: ";
      ballmessage += eightball_();
      ballmessage += "!";

      logmsg(ballmessage.c_str());
    } else if (message.find("reverse:") == 0) {
      if (NULL == reverse_) {
        logmsg("Reverse library not loaded");
        return;
      }

      std::string s = message.substr(strlen("reverse:"));
      char* result = reverse_(s.c_str());

      std::string message = "Your string reversed: \"";
      message += result;
      message += "\"";

      free(result);

      logmsg(message.c_str());
    } else {
      std::string errormsg = "Unexpected message: ";
      errormsg += message;
      logmsg(errormsg.c_str());
    }
  }

  static void* LoadLibrariesOnWorker(void* pInst) {
    DlOpenInstance* inst = static_cast<DlOpenInstance*>(pInst);
    inst->LoadLibrary();
    return NULL;
  }

 private:
  void* eightball_so_;
  void* reverse_so_;
  TYPE_eightball eightball_;
  TYPE_reverse reverse_;
  pthread_t tid_;
};

class DlOpenModule : public pp::Module {
 public:
  DlOpenModule() : pp::Module() {}
  virtual ~DlOpenModule() {}

  // Create and return a DlOpenInstance object.
  virtual pp::Instance* CreateInstance(PP_Instance instance) {
    return new DlOpenInstance(instance);
  }
};

namespace pp {
Module* CreateModule() { return new DlOpenModule(); }
}  // namespace pp

/* [<][>][^][v][top][bottom][index][help] */