Boost logo

Boost :

Subject: [boost] 2nd try, New library proposal: PolicyLoader
From: Rob Meijer (rob_at_[hidden])
Date: 2009-11-12 02:11:12


I posted this to this list ones before (as the site sugests), and didn't
get any response, possibly becource it is simply to useless for you guys
to reply to, but I'm not sure.

If it is indeed useless please let me know, so I know not to put any
effort in it.

The Open Computer Forensics Architecture Library (OcfaLib)
hides a litle piece of template code for loading a class from a
dynamically loaded library. Although this code is currently bound to
OcfaLib and usage on *NIX systems, I wondered if the concept used would
not be extendable to a generically usable library for this purpose.

I've tried to strip the OCFA specific code to show the simple templating
concept of this library. I would like to know if it is a good idea to
work on this code in order to make it a powerfull cross-platform boost
library that addresses this issue in an even more generic way. If it is
useless, please also let me know.

First lets show an example of usage:

  typedef SinglePointerConstructor<AbstractRepository,const char> CRepositoryType;
  PolicyLoader<CRepositoryType> pl(myLib,"createRepository");
  CRepositoryType *constructor=pl.constructor();
  _instance = (*constructor)(repRoot.c_str());

Here the 'AbstractRepository *' type _instance gets assigned a new object
of a class that implements AbstractRepository to it, that is created with
the "createRepository" function in the so file designated by myLib.

Here is the stripped down template code:
----------------------------------
template <class T,class U>
class SinglePointerConstructor {
  public:
    typedef T * (*fp)(U *);
    SinglePointerConstructor (fp func) : mFunction(func) {}
    T *operator() (U *val) {
      return (mFunction)(val);
    }
  private:
    fp mFunction;
};

template <class T>
class VoidToFunction {
 public:
  static T *cast(void *p) {
#ifdef VOID_FP_CAST_WORKAROUND
#ifdef POINTERS_64BIT
      return new T(reinterpret_cast<typename T::fp>(reinterpret_cast<long long>(p)));
#else
      return new T(reinterpret_cast<typename T::fp>(reinterpret_cast<int>(p)));
#endif
#else
      return new T(reinterpret_cast<typename T::fp>(p));
#endif
  };
};

class PolicyLoader: {
  public:
        PolicyLoader(std::string myLib,std::string loadername):mLibHandle(0),mConstructor(0) {
           mLibHandle=dlopen(myLib.c_str(),RTLD_NOW|RTLD_GLOBAL);
           if (mLibHandle == 0) {
              throw std::runtime_error( std::string("Problem loading library '") +
                                         myLib +
                                         std::string("' (") +
                                         std::string(dlerror()) +
                                         std::string(")")
                                      );
           }
           mConstructor = VoidToFunction<TConstructor>::cast(dlsym(mLibHandle,loadername.c_str()));
           if (mConstructor == 0) {
              std::string errString=std::string("Problem looking up symbol '") + loadername + std::string("' in library '") +
                      myLib + std::string("' (") + std::string(dlerror()) + std::string(")");
              dlclose(mLibHandle);
              throw std::runtime_error(errString);
           }
        }
        ~PolicyLoader() {
           delete mConstructor;
        }
        void closeLib() {
           if (mLibHandle) {
              dlclose(mLibHandle);
           }
           mLibHandle=0;
        }
        TConstructor *constructor() {
           return mConstructor;
        }
  private:
        void *mLibHandle;
        TConstructor *mConstructor;
};
 
-----------------


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk