Thread: Best way to allow plugins for my program?

  1. #1
    mustang benny bennyandthejets's Avatar
    Join Date
    Jul 2002
    Posts
    1,401

    Best way to allow plugins for my program?

    I'm in design stages of a program, but I'm a bit stuck because I'm not sure how to best implement a plugin system. I want authors of plugins to be able to add functionality to my program. Should each plugin be contained in a DLL, and if so, how can I provide access to my program? Would COM be a good way?
    [email protected]
    Microsoft Visual Studio .NET 2003 Enterprise Architect
    Windows XP Pro

    Code Tags
    Programming FAQ
    Tutorials

  2. #2
    Registered User Codeplug's Avatar
    Join Date
    Mar 2003
    Posts
    4,981
    Simple DLL approach:
    - come up with a good/stable API for your plugin architecture
    - use an ini file or the registry to enumerate all the 3rd party DLL plugins
    - load up the DLL's and start making calls into them

    The nice thing about going with DLL's vs. COM objects is that the plugin writer doesn't have to be COM savvy

    The first step is coming up with an appropriate set of API's that you expect to find in the plugin DLL, and when those API's are called. The first API called with probably be some sort of registration call, which can be as simple as "void Init()", or something more complex.

    Hashing out the actual API's (or "plugin architecture") will depend on what functionality the plugin is actually providing to your app.

    gg

  3. #3
    mustang benny bennyandthejets's Avatar
    Join Date
    Jul 2002
    Posts
    1,401
    Thanks for the advice. Say for example, I want the plugin to have three functions, Init(), Draw(HDC) and Quit(). How would the DLL be written, and how would I call those functions from the main program? I'm guessing some of the code would be like this:

    Code:
    //Dll source
    void Init()
    {
        MessageBox(NULL,"Plugin loaded",NULL,NULL);
    }
    
    void Draw(HDC hdc)
    {
        string strTemp="This is the plugin Draw function";
        TextOut(hdc,0,0,strTemp.c_str(),strTemp.length());
    }
    
    void Quit()
    {
        MessageBox(NULL,"Unloading Plugin",NULL,NULL);
    }
    Code:
    //Main program
    void LoadPlugins()
    {
    	for (int i=0;i<numPlugins;i++)
    	{
    		Handles[i]=LoadLibrary(Plugins[i]);
    		Init(); //Is this right? Somehow I dont think so
    	}
    }
    
    //Sometime later...
    void OnDraw(HDC hdc)
    {
    	Draw(hdc); //This is surely not right
    }
    
    //Sometime later...
    void UnloadPlugins()
    {
    	for (int i=0;i<numPlugins;i++)
    	{
    		Quit(); //Surely not correct
    		FreeLibrary(Handles[i]);
    	}
    }
    Now that I think about it, would I use the GetProcAddress() function?
    [email protected]
    Microsoft Visual Studio .NET 2003 Enterprise Architect
    Windows XP Pro

    Code Tags
    Programming FAQ
    Tutorials

  4. #4
    Registered User
    Join Date
    May 2004
    Posts
    23
    Yes. First you LoadLibrary as you have there then GetProcAddress on each function exported from the dll you wish to use.

    You've got it

  5. #5
    mustang benny bennyandthejets's Avatar
    Join Date
    Jul 2002
    Posts
    1,401
    Thank you.
    [email protected]
    Microsoft Visual Studio .NET 2003 Enterprise Architect
    Windows XP Pro

    Code Tags
    Programming FAQ
    Tutorials

  6. #6
    mustang benny bennyandthejets's Avatar
    Join Date
    Jul 2002
    Posts
    1,401
    I have a couple of questions:

    1. After I use GetProcAddress(), how do I call the function?
    2. Can I call DLL functions that have different return types and parameter lists?
    [email protected]
    Microsoft Visual Studio .NET 2003 Enterprise Architect
    Windows XP Pro

    Code Tags
    Programming FAQ
    Tutorials

  7. #7
    Yes, my avatar is stolen anonytmouse's Avatar
    Join Date
    Dec 2002
    Posts
    2,544
    >> . Can I call DLL functions that have different return types and parameter lists? <<
    Realistically, you need to know the return type, calling convention and parameter list at compile time.

    >> After I use GetProcAddress(), how do I call the function? <<
    Here is an example of a function that uses dynamic loading of functions:

    Code:
    BOOL EnableProcessPrivilege(LPCTSTR lpPrivilege) 
    {
    	/* This function enables a privilege for the current process */
    	/* lpPrivilege can be either a privilege constant eg. SE_SHUTDOWN_NAME
    	 * which is DEFINEd in the windows headers to the string 
    	 * "SeShutdownPrivilege" or the string can be used directly. */
    
    	typedef BOOL (WINAPI * fnptr_openprocesstoken)(HANDLE,DWORD,PHANDLE);
    	typedef BOOL (WINAPI * fnptr_adjusttokenprivileges)(HANDLE,BOOL,PTOKEN_PRIVILEGES,DWORD,PTOKEN_PRIVILEGES,PDWORD);
    	typedef BOOL (WINAPI * fnptr_lookupprivilegevalue)(LPCTSTR,LPCTSTR,PLUID);
    
    	TOKEN_PRIVILEGES tp       = { 0 };
    	LUID             luid     = { 0 };
    	HANDLE           hToken   = NULL;
    	HMODULE          hAdvapi  = NULL;
    
    	if (!(hAdvapi = LoadLibrary(TEXT("Advapi32.dll"))))
    	{
    		return FALSE;
    	}
    
    	fnptr_openprocesstoken       openprocesstoken      = (fnptr_openprocesstoken)      GetProcAddress(hAdvapi, "OpenProcessToken");
    	fnptr_adjusttokenprivileges  adjusttokenprivileges = (fnptr_adjusttokenprivileges) GetProcAddress(hAdvapi, "AdjustTokenPrivileges");
    	fnptr_lookupprivilegevalue   lookupprivilegevalue  = (fnptr_lookupprivilegevalue)  GetProcAddress(hAdvapi, "LookupPrivilegeValueA");
    
    	if (!openprocesstoken || !adjusttokenprivileges || !lookupprivilegevalue)
    	{
    		FreeLibrary(hAdvapi);
    		return FALSE;
    	}
    
    	/* Get the local id of our desired privilege */
    	if (!lookupprivilegevalue(NULL, lpPrivilege, &luid))
    	{
    		FreeLibrary(hAdvapi);
    		return FALSE; 
    	}
    
    	/* Fill in TOKEN_PRIVILEGES structure */
    	tp.PrivilegeCount           = 1;
    	tp.Privileges[0].Luid       = luid;
    	tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
    
    	/* Get the access token for the current process */
    	if (!openprocesstoken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken))
    	{
    		FreeLibrary(hAdvapi);
    		return FALSE; 
    	}
    
    	/* Enable the privilege */
    	if (!adjusttokenprivileges(hToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), NULL, NULL))
    	{
    		FreeLibrary(hAdvapi);
    		CloseHandle(hToken);
    		return FALSE; 
    	}
    
    	FreeLibrary(hAdvapi);
    	CloseHandle(hToken);
    
    	return TRUE;
    }
    Note, the syntax of the typedefs. See http://www.function-pointer.org/ for more details.
    Last edited by anonytmouse; 05-26-2004 at 09:26 PM.

  8. #8
    mustang benny bennyandthejets's Avatar
    Join Date
    Jul 2002
    Posts
    1,401
    Cheers, I understand now.
    [email protected]
    Microsoft Visual Studio .NET 2003 Enterprise Architect
    Windows XP Pro

    Code Tags
    Programming FAQ
    Tutorials

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Need help with a program, theres something in it for you
    By engstudent363 in forum C Programming
    Replies: 1
    Last Post: 02-29-2008, 01:41 PM
  2. Replies: 4
    Last Post: 02-21-2008, 10:39 AM
  3. Replies: 3
    Last Post: 03-04-2005, 02:46 PM
  4. My program, anyhelp
    By @licomb in forum C Programming
    Replies: 14
    Last Post: 08-14-2001, 10:04 PM