1
      2
      3
      4
      5
      6
      7
      8
      9
     10
     11
     12
     13
     14
     15
     16
     17
     18
     19
     20
     21
     22
     23
     24
     25
     26
     27
     28
     29
     30
     31
     32
     33
     34
     35
     36
     37
     38
     39
     40
     41
     42
     43
     44
     45
     46
     47
     48
     49
     50
     51
     52
     53
     54
     55
     56
     57
// Author:       Andreas F. Borchert
// Description:  register functions by their name

// hack: MAC OS X is not POSIX conform :(
#ifndef __MACH__
#include <link.h>
#endif

#include <dlfcn.h>
#include <string>
#include "DynFunctionRegistry.hpp"

DynFunctionRegistry::DynFunctionRegistry() {
}

DynFunctionRegistry::DynFunctionRegistry(const std::string& dir) :
      dir(dir) {
}

void DynFunctionRegistry::add(Function* f) {
   registry[f->get_name()] = f;
// FunctionRegistry::add

typedef Function* FunctionConstructor();

Function* DynFunctionRegistry::dynload(const std::string& name) {
   std::string path = dir;
   if (path.size() > 0) path += "/";
   path += name; path += ".so";
   void* handle = dlopen(path.c_str(), RTLD_LAZY | RTLD_LOCAL);
   if (!handlereturn 0;
   FunctionConstructor* constructor =
      (FunctionConstructor*) dlsym(handle"construct");
   if (!constructor) {
      dlclose(handle); return 0;
   }
   return constructor();
}

bool DynFunctionRegistry::is_known(const std::string& fname) {
   return get_function(fname) != 0;
// FunctionRegistry::is_known

Function* DynFunctionRegistry::get_function(const std::string& fname) {
   auto it = registry.find(fname);
   Function* f;
   if (it == registry.end()) {
      f = dynload(fname);
      if (f) {
         add(f);
         if (f->get_name() != fname) registry[fname] = f;
      }
   } else {
      f = it->second;
   }
   return f;
// FunctionRegistry::get_function