• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 428
  • Last Modified:

Integration of plug-ins in a dialog based app

Hello, first I'll talk about the application in general, then what and how I expect plug-ins to work in it.

First of all, I have an MFC dialog based application which can communicate in plain text to servers or act as a server (TCP/UDP) and I want to integrate some plug-ins to support automation of specific procotol, like FTP, IRC, etc... So I thought instead of hard coding them I would have plug-ins you can load when you want to add support to some particular protocol. I will have an option window where you can add and select which plug-ins will be used and configure them. That window will contain a tab control which first tab is the plug-in selection and other tabs are added with each plug-ins you load so you can configure them.

More technically, when a plug-in is loaded, it will parse incoming text, like:
Received buffer = "PING :0123456\r\n"
and if it match one of the right command, like the PING above, will answer with the proper command:
Send to server : "PONG irc.someserver.net :0123456\r\n"
This is the most important part of the job I need to have working to make those plug-ins useful.

Now I would like to know what is the best way to implent this kind of architecture, how can I make the plug-ins access variables of my main program and receive messages. I'm fairly new to DLLs and only know how to make static DLLs as now.

If you need Any information, just ask, I will be pleased to answer back! Any links, sample code, information or comments will be greatly appreciated.

Thanks in advance!
0
TiCpu
Asked:
TiCpu
  • 6
  • 5
  • 4
2 Solutions
 
AlexFMCommented:
You need to define plug-ins interface: list of functions implemented by plug-ins Dll. The simplest way is exposing C-style interface: Dll exports functions (API). Client loads Dll using LoadLibrary function, get pointers to exported functions using GetProcAddress, and calls these functions.
0
 
TiCpuAuthor Commented:
Just to be sure everything is understood, (not sure about what you are saying will work the way I want, already heard this for some static dll), does that way the program will be able to load new DLLs without having to be recompiled and work with them independently ?
0
 
AlexFMCommented:
Yes. Program is not statically linked to plug-ins Dll. It gets Dll name at run time, loads Dll by name and tries to call functions which must be exported from this Dll. If Dll doesn't have some function, GetProcAddress returns NULL.
To understand this better, I suggest you to write two sample projects. One is Dll which exports some function, for example:

int SomeFunction(char c);

Second is exe client which calls this Dll statically:

typedef int (*SOMEFUNCTION)(char);


HMODULE hDll = LoadLibrary(sDllName);   // set here full Dll name - for example, take it from Open File Dialog
if ( hDll )
{
      SOMEFUNCTION function_ptr = (SOMEFUNCTION) GetProcAddress(hDll , _T("SomeFunction"));

      if ( function_ptr )
      {
            int n = (function_ptr)('a');   // call function by pointer
      }

      FreeLibrary(hDll);
}

This code can call SomeFunction from any Dll which exports it.
0
Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
jkrCommented:
This way you could load a 'factory function' from a plugin DLL. Starting from there, I'd choose the 'classic' way to use pure virtual interfaces, like e.g.

interface IPluginBase {

    enum PluginType {
        //...
    };

    virtual void GetImplementation ( enum PluginType) = 0;
    virtual void AddRef () = 0;
    virtual void Release () = 0;
};

which would allow you to put each plugin in a DLL that exports a

IPluginBase* GetPlugin ();

and load it at runtime to query what's in the plugin. As you can see, this is already quite similar to COM/ActiveX (IUnknown in particular), with the latter sparing you the 'burden' to code the loading/activation overhead.
0
 
AlexFMCommented:
Very good idea which combines simplicity of C-style interface (no COM headache) and advantages of OOP. My five cents: add also function:

void Release(IPluginBase*);
0
 
AlexFMCommented:
Oops, there is already AddRef and Release. Anyway, GetPlugin + Relase may be simpler than GetPlugin + AddRef + Release.
0
 
TiCpuAuthor Commented:
Ok, now I've tried first with AlexFM said, the code is logic and should work... but doesn't, I tried it, it can LoadLibrary (I get non-null hDll and have the dialog box I inserted in InitInstance of the dll popup) but GetProcAddress return 0 for some reason,  I have this in the DLL:
int CIRCApp::SomeFunction(CString text)
{
      return MessageBox(NULL, "Some text", "Some caption", MB_OKCANCEL);
}
and the same code as for my client except CString instead of char in typedef.

Found it while I was typing, I added it in IRC.def but now when function in my client return it crashes.

for the jkr code, I don't get it right now, is that what you put in DLL, yes? and how do I proceed to call those functions in the program then?
0
 
jkrCommented:
>>GetProcAddress return 0 for some reason

You cannot obtain the address of a method like the above from a DLL.
0
 
TiCpuAuthor Commented:
Oh, found out some information while running it in debug, when function is about to exit (at } ) it spit out this
Run-Time Check Failure #0 - The value of ESP was not properly saved across a function call.  This is usually a result of calling a function declared with one calling convention with a function pointer declared with a different calling convention.
and then if I click Continue I get the error.
0
 
TiCpuAuthor Commented:
No more explanations on your method jkr ? I really don't know how to put this in my code to make it work correctly.
0
 
TiCpuAuthor Commented:
I finally found out how to get ride of the error when returning, added CALLBACK* before SOMEFUNCTION and now it works like a charm, but I really would like to hear more about jkr's method so I can choose between both of them AlexFM was loking enthousiast about it too.

Thanks.
0
 
jkrCommented:
>> No more explanations on your method jkr ?

*YAWN* it is 4:10am here :o)

The idea is that pure virtual interfaces do nothing else but describe the functionality of an object to the outside, which you can bring to life using different implementations, e.g.

interface IHuman {

  enum Gender{
    IsMale,
    IsFemale
   };

  virtual void Talk () = 0;

};

class Man : public IHuman {

public:
  virtual void Talk () { cout << "Nothing to say" << endl;}

};

class Woman : public IHuman {

public:
  virtual void Talk () { cout << "Well, I just learned about that cute story that really..." << endl;}

};

and have your DLL export a function like

IHuman* CreateHuman( IHuman::Gender g) {

  if ( g == IsFemale) return new Woman;

  return new Man;

}

Hope you got the idea :o)
0
 
jkrCommented:
Oops, that should read

IHuman* CreateHuman( IHuman::Gender g) {

 if ( g == IHuman::IsFemale) return new Woman;

 return new Man;

}
0
 
AlexFMCommented:
jkr's method is extesion of simple IPI method. Suppose you want to solve this problem by C++ way. Let's say that every plugin Dll should supply to caller some class and not set of functions. Interface defines what functions this class supports. Every plugin class should be derived from this interface and implement it's functions.
To expose this class for client we can use simple API way which you already know. Exported functions may look like this:

// Dll code
IPluginBase* GetPlugin ()
{
    CPluginImpl* pPlugIn = new CPluginImpl();   // CPluginImpl is class derived from IPluginBase
    return;
}

void ReleasePlugin(IPluginBase* pPlugIn)
{
     delete (CPluginImpl*)pPlugIn;
}

Client code:

typedef IPluginBase* (*GETPLUGIN)();
typedef void (*RELEAEPLUGIN)(IPluginBase*);


HMODULE hDll = LoadLibrary(sDllName);
if ( hDll )
{
      GETPLUGIN get_ptr = (GETPLUGIN) GetProcAddress(hDll , _T("GetPlugin"));
      RELEAEPLUGIN release_ptr = (RELEAEPLUGIN) GetProcAddress(hDll , _T("ReleasePlugIn"));

      if ( get_ptr  &&  release_ptr )
      {
            IPluginBase* pPlugIn = (get_ptr)();

            // use plug-in here:
            // pPlugIn->DoSomething();
            // ...

            (release_ptr)(pPlugIn);
      }

      FreeLibrary(hDll);
}
0
 
TiCpuAuthor Commented:
Yes, with more reading I was able to understood everything you all said and now I can at least make a dialog appear in a tab (but dialog still have a background in the tab which kills XP look) but I'll manage to get it working, thanks for all the tips/code example!
0

Featured Post

VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

  • 6
  • 5
  • 4
Tackle projects and never again get stuck behind a technical roadblock.
Join Now