Home » C++

A Simple Plugin Architecture For C++

18 June 2003 131,499 views 6 Comments

A Simple Plugin Architecture For C++ continued…

This is the routine that scans the directory to see if we have any plugins available. We simply pass it the directory path name for it to check. We can also pass an optional value of true or false to indicate if we wish to add the plugins to the current list, or to start afresh.

void PluginManager::getPluginList(char * dirPath, bool addToList)
{      
   if(!addToList) clearPluginList();
   
   //Construct the directory path and use a wildcard
   char fname[MAX_PATH];
   strcpy(fname,dirPath);
   size_t len=strlen(fname);
   if(fname[len-1]=='/' || fname[len-1]=='\\')   strcat(fname,"*.dll");
   else strcat(fname,"\\*.dll");
   
   WIN32_FIND_DATA fd;
   HANDLE hFind = FindFirstFile(fname, &fd); 

   if(hFind == INVALID_HANDLE_VALUE) 
   {
      FindClose(hFind);
      return;
   }

   do
   { 
      HINSTANCE dllHandle = NULL;
      
      //Use a 'try' just in case there are any badly formed DLLs
      try
      {
         if(!(fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
         {               
            dllHandle = LoadLibrary(fd.cFileName);
            if(dllHandle != NULL) 
            {               
               PLUGIN_FACTORYFUNC funcHandle;
               funcHandle = reinterpret_cast<PLUGIN_FACTORYFUNC>
                              (GetProcAddress(dllHandle, "makePlugin"));
             
               //Check to see if the factory function is present                 
               if(funcHandle !=NULL)
               {                     
                  PluginDetails * curPlugin = new PluginDetails();
                  curPlugin->setFileName(fd.cFileName);

                  PLUGIN_TEXTFUNC textFunc;                
                  //Store the plugin name
                  textFunc = reinterpret_cast<PLUGIN_TEXTFUNC>
                              (GetProcAddress(dllHandle, "getPluginName"));
                  curPlugin->setName(textFunc());
                  
                  //Store the plugin type
                  textFunc = reinterpret_cast<PLUGIN_TEXTFUNC>
                              (GetProcAddress(dllHandle, "getPluginType"));
                  curPlugin->setType(textFunc());                  

                  //Add the plugin
                  pluginRegister.push_back(curPlugin);
               }
               FreeLibrary(dllHandle);
            }
         }
      }
      catch(...)
      {
         if(dllHandle != NULL) FreeLibrary(dllHandle);
      }
   } while(FindNextFile(hFind, &fd));
   FindClose(hFind); 
}

On the next page I’ll show you an example of calling this routine from your main application, and you can also download the source and project for this tutorial.

1 Star2 Stars3 Stars4 Stars5 Stars (4 votes, average: 4.00 out of 5)
Loading...

6 Comments »

  • Coder said:

    Hey, thanks for posting this example. Also thanks for posting the C++ source code examples, very helpful! 🙂

  • AndyN (author) said:

    Hey, no problem! This is an old one. I’m happy you and others are still getting some use from this 🙂

    Andy

  • Browner87 said:

    You don’t have any example of how to return pointers from a function. Is this possible using ANSI C++? Can you return a (char *) from the shared library to the main program?

  • AndyN (author) said:

    It’s been a long time since I’ve looked into this, but I’m pretty sure the answer’s no. I have a feeling that the dll and the main program don’t share memory space, and if you try to free memory that was allocated by the other, it’ll throw an error.

    If that’s the case, then the only way you could make this work would be to pass some sort of factory function to the plugin to allocate memory in the right place. That way the responsibility lies with the main process to free the memory later, plus it can safely unload the dll at any stage without memory leaks.

  • Browner87 said:

    Well, the pointer returning does work (it was other code that I had that was casing the problem). As for memory leaks, I don’t know. I found a better to achieve what I wanted so I only did it for experience.

    May I suggest that Linux programmers however read the following article if you are trying to implement this on Linux:
    http://www.linuxjournal.com/article/3687

  • AnhMV said:

    Thanks for this post