Boost logo

Boost :

From: Eric Boutin (eric_at_[hidden])
Date: 2003-12-03 21:37:30


here's the code :

////////////////////////////////////////////////////////////////////////////
///////////////////////
caller-side code :
////////////////////////////////////////////////////////////////////////////
///////////////////////

/****
* loadlib.hpp : the declaration/definition or the dynamicfunction class
*
* this class calls a run-time librairy using system( ) with a 2 arguments
plus the librairy names (3 arg total)
*
* "librairyfilename" "inputfilename" "outputfilename"
*
* it creates a input and a output file
* the input files is the fallowing format :
* thenameofthefunctiontocall
* firstarg
* secondarg
* thirdarg
*
* to parse it, it's quite easy to do.. getline(file, buffer), function to
call = buffer; vector<string> argv; then while(getline( ))
* you can push_back the value at the end of the vector..
*
* the output file is the output generated by the function.. thoses are
programmers/functions-specifics
*
* for more info about librairy-side parsing, see dynamiclib.hpp
*
****/

//Copyleft - Eric Boutin - december 2003
//this class loads a function from a dynamic librairy and runs it
//sorry if it's messy.. I want this to fit in an include file so no linking
needed..
//sorry

#include <string>
#include <fstream>
#include <vector>
#include <cstdlib>
#include <sstream>

class dynamicfunction {
protected:
 std::string outfilename; //the program will output everything in this file
 std::string argfilename; //this file will be passed to the program, first
line : function to be called, second line and on arguments, to be reputed on
a vector
 std::string libpath; //this contains the path to the librairy
 std::string functiontocall; //the name of the function to call
    //internal state for genfilename( );
 std::vector<std::string> argv; //thoses arguments will be passed to the
program.. to simplify the implementation

   //this function generates file names and make shure they are unused
   void genfilename(std::string beg, std::string& buff, std::string end) {
    static unsigned int genfilenamefeed=0; /* keeps internal state */
    genfilenamefeed++;

   //first, create a string that have what we want;
    std::ostringstream ss;
    ss <<"./" << beg << genfilenamefeed << end;
    std::string filename = ss.str();

   //check if the file exist
    std::ifstream file;
    file.open(filename.c_str());
    if(!file) {
     //file doesn't exist;
     buff = filename;
     return;
    }
   //file exist, loop back;
    genfilename(beg, buff, end); }

public:
  void pushargv(std::string in) {argv.push_back(in); return; } //Some
accessors -> this one pushes an argument
  void cleanup() { remove(argfilename.c_str());
remove(outfilename.c_str()); } // " " -> this one cleanup the tmp
files.. called by the destructor or when your done with the function.. but
be carefull !

  dynamicfunction(std::string libpathb, std::string functiontocallb) {
   libpath = libpathb;
   functiontocall = functiontocallb;
   genfilename("tmplibcall_input", argfilename, ".tmp");
   genfilename("tmplibcall_output", outfilename, ".tmp");
  }//ok we know where everything is.. now let the user pushargv( ) some
times..

  //ok now call the lib, so it'll call and execute the function eventually

  int go(std::istream& progoutput) {
  //1) put argv in a file (argfilename)
  //2) call the lib
  //3) fill the istream reference with the file corresponding to the
outputfile and returns the function return value
   std::ofstream file;
   file.open(argfilename.c_str());
   file << functiontocall << std::endl;
   std::vector<std::string>::iterator iter;

   for(iter = argv.begin(); iter != argv.end(); iter++) { file << *iter <<
std::endl;}

   file.close();

   //on windows, when presence of whitespace in the filenames, we have to
double quote, else cmd is all messed up
   //we want to achieve this command : "pathtolib" "inputfilename"
"outputfilename"
   std::ostringstream ss;
   ss << "\"\"" << libpath << "\" \"" << argfilename << "\" \"" <<
outfilename << "\"\"";

   std::string callstring = ss.str();
   int err = system(callstring.c_str());
   //if( err < 0) { return std::istringstream("");} //TODO, better error
handling
   progoutput = std::ifstream(outfilename.c_str());
   return err;
  }

  ~dynamicfunction() {cleanup();}

};

#endif

////////////////////////////////////////////////////////////////////////////
////////////////////////////////
this is the librairy-side doc
////////////////////////////////////////////////////////////////////////////
/////////////////////////////

/*******
* Eric Boutin, Copyleft, december 2003
* dynamiclib.hpp : the class that takes care of exporting functions and
calling the called functions.. kind of a link after main and before
* the exported functions
* HOW TO USE IT:
* first, at the beggining of ONE file, put the word USEDYNAMICLIB, it
define some static variables and functions, and main( )
* second, export functions
*
* Exporting functions:
* to begin, you put a BEGIN_EXPORTLIST statement at the top
* the you put some statement like this : EXPORT("functionname",
functionname);
* then you finish with a END_EXPORTLIST statement at the end
*
* Example:

int functiona(ostream& out, vector<string> argv);
int functionb(ostream& out, vector<string> argv);

BEGIN_EXPORTLIST
 EXPORT("functiona", functiona);
 EXPORT("functionb", functionb);
END_EXPORTLIST

* Once your done with exporting functions, you can define the functions..
that's always a good idea..
*
* the functions should returns an int, and must accept -> std::ostream&, you
can use this ostream to output all data there..
* -> vector<string>, all arguments are there
*
* Note that the input file is so easy to parse that any langage can parse
it.. you are not limited to this implementation of the librairy..
* write your own one in another programming langage !! e-mail me if you
wrote a perl of sed or awk or java one.. I'll use it !
*
*******/

//at the top of the main file in the dynamic librairy, put USEDYNAMICLIB to
define some static variables and functions

#define DYNAMICLIB_MISUAGE -80000 //wrong argc
#define DYNAMICLIB_BADFILES -80001 //!file failed
#define DYNAMICLIB_NOTEXPORTED -80002 //the function was not exported

#define BEGIN_EXPORTLIST void EXPORT() {
#define END_EXPORTLIST }

#include <map>
#include <string>
#include <fstream>
#include <vector>

    //the maker of the librairy must implement this one
extern "C" void EXPORT(); //global C export function; so easy interface with
C

class dynamiclib{
protected:
 std::ofstream out; //output everything here please
 std::ifstream in;
 static std::map<std::string, int (*)(std::ostream&,
std::vector<std::string>)> functionarray;
 static std::map<std::string, bool> definedfunction;
 std::vector<std::string> arg;
 static dynamiclib* lib;
 std::string functiontocall;

public:
 dynamiclib() {dynamiclib::lib = this;}
 static void export(std::string functioname, int (*funct)(std::ostream&,
std::vector<std::string>)) {
  functionarray[functioname] = funct; definedfunction[functioname] = true;}
 static void EXPORT() {::EXPORT(); }

  int go(int argc, char* argv[]) {
   EXPORT(); //first step, export the functions
   //ok real job begins
  //1) check argc and open streams
   if(argc != 3) {return DYNAMICLIB_MISUAGE;}
   //ok argv is ok.. at least we think...
   in.open(argv[1]);
   out.open(argv[2]);
   if(!(in && out)) { return DYNAMICLIB_BADFILES;}

  //2) parse in
  //firstline is the function to call, every other lines are arguments
   std::string buff;
   std::getline(in, functiontocall);
   while(std::getline(in, buff)) { arg.push_back(buff);}

  //3) call the function
   if(definedfunction[functiontocall]) {
    return functionarray[functiontocall](out, arg);} else {
    //the function wasn't exported
    return DYNAMICLIB_NOTEXPORTED;}

  }
};

#define USEDYNAMICLIB std::map<std::string, int
(*)(std::ostream&,std::vector<std::string>)> dynamiclib::functionarray;\
      std::map<std::string, bool> dynamiclib::definedfunction; \
      dynamiclib* dynamiclib::lib; \
      int main(int argc, char* argv[]) { dynamiclib lib; return lib.go(argc,
argv); } \
      void EXPORT(std::string functionname, int (*funct)(std::ostream&,
std::vector<std::string>)){ dynamiclib::export(functionname, funct);}

//end of the INITDYNAMICLIB macro
#endif


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