return to first page linux journal archive
keywordscontents

Listing 4. Source for Main Program Invoking Dynamically Loaded Classes Circle and Square

#include <iostream> 
#include <map> 
#include <list> 
#include <vector>
#include <string> 
#include <dlfcn.h> 
#include <stdio.h> 
#include <unistd.h> 
#include "shape.hh"
// size of buffer for reading in directory entries 
static unsigned int BUF_SIZE = 1024;
// our global factory for making shapes 
map<string, maker_t *, less<string> > factory;
int main(int argc, char **argv){
   FILE *dl;   // handle to read directory 
   char *command_str = "ls *.so";  // command
               // string to get dynamic lib names
   char in_buf[BUF_SIZE]; // input buffer for lib
                          // names 
   list<void *> dl_list; // list to hold handles
                               // for dynamic libs 
   list<void *>::iterator itr; 
vector<string> shape_names;  // vector of shape
               // types used to build menu
   list<shape *> shape_list;  // list of shape 
               // objects we create
   list<shape *>::iterator sitr; 
map<string, maker_t *, less<string> >::iterator fitr;
   // get the names of all the dynamic libs (.so 
              // files) in the current dir 
   dl = popen(command_str, "r"); 
   if(!dl){
      perror("popen");
      exit(-1);
   }
   void *dlib; 
   char name[1024]; i
   while(fgets(in_buf, BUF_SIZE, dl)){
      // trim off the whitespace 
      char *ws = strpbrk(in_buf, " \t\n"); 
      if(ws) *ws = '\0';
      // append ./ to the front of the lib name
      sprintf(name, "./%s", in_buf); 
      dlib = dlopen(name, RTLD_NOW);
      if(dlib == NULL){
         cerr << dlerror() << endl; 
         exit(-1);
      }
      // add the handle to our list
      dl_list.insert(dl_list.end(), dlib);
   }
   int i = 0; 
   // create an array of the shape names
   for(fitr=factory.begin(); fitr!=factory.end();
        fitr++){
      shape_names.insert(shape_names.end(), 
        fitr->first);
      i++;
   }
   int choice;<\n> 
   // create a menu of possible shapes to create and let the user make some 
   while(1){
      i = 1;
      for(fitr=factory.begin(); 
           fitr!=factory.end(); fitr++){
         cout << i << " - Create " << fitr->first 
            << endl; 
         i++;
      }
      cout << i << " - Draw created shapes\n"; 
      i++; i
      cout << i << " - Exit\n"; 
      cout << "> "; 
      cin >> choice;
      if(choice == i){
         // destroy any shapes we created
         for(sitr=shape_list.begin();
              sitr!=shape_list.end();sitr++){
            delete *sitr;
         }
         // close all the dynamic libs we opened
         for(itr=dl_list.begin(); itr!=dl_list.end(); itr++){
            dlclose(*itr);
         }
         exit(1);
      }
      if(choice == i - 1){
         // draw the shapes
         for(sitr=shape_list.begin();
              sitr!=shape_list.end();sitr++){
            (*sitr)->draw();
         }
      }
      if(choice > 0 && choice < i - 1){
         // add the appropriate shape to the shape list
         shape_list.insert(shape_list.end(), 
            factory[shape_names[choice-1]]());
      }
   }
}