I am attempting to use classes that are defined in my custom written DLLs. I am dynamically loading the DLLs using LoadLibrary. I already know how to access functions using GetProcAddress.
Is it possible to do something similar for classes
No! You can not use class exports via this way with LoadLibrary.
A simple approach is to create interfaces like COM interfaces and return only pointers to those interfaces from the DLL. This is alaso a very flexible aproach and you hide the implementation details fully.
You're describing the concept of interfaces (which is an abstract base class). Interfaces don't have definitions, only prototypes. Hence they wouldn't be "defined in the main program."
COM objects don't support implementation inheritance. .NET objects, however do (but only single inheritance.)
This is the most simple design, that hides every complexity inside the plugin and the way how the interface cooperates is simple enough too!
Thats the way COM works, if not working accross apartment boundaries or processes.
Now the last hint from me: Take care about the parameters you pass by the interface, don't use STL classes. Restrict yourself to the basic types and when needed use SafeArray or BSTR. Don't perform allocation and deallocations across modules, in other words: don't allocate memory in the add in and free it in the program, unless you use safe types like BSTRs or SafeArrays!
You can export classes from a DLL. A solution to your issue would be to put VirtTestBase in a DLL and then export it. The plugin can then derive from the exported class.
Right off the bat, I just want to say thank you very much Brian. I think I have the general idea here and you are certainly helping me nail down the specifics.
I have created a prototype in my main program;
class
VirtTestBase
{
protected
:
int width, height;
public
:
void set_values (int , int );
void printarea (void);
virtual int area (void) =0;
VirtTestBase(
void);
~VirtTestBase(
void);
};
and also, the implementation
#include
"StdAfx.h"
#include
".\virttestbase.h"
#include
<windows.h>
VirtTestBase::VirtTestBase(
void)
{
}
VirtTestBase::~VirtTestBase(
void)
{
}
void
VirtTestBase::set_values(int a, int b) {
width=a;
height=b;
}
void
VirtTestBase::printarea(void) {
CString message;
message.Format( "%d" ,
this->area() );
MessageBox(NULL, message, "This message box brought to you by a VirtTestBase class instance.",MB_OK);
}
In my plugin I have create a class which is to inherit from this class defined in the main program with the definition
withing the main program I am attempting to use the class from the plugin by
VirtTestBase * vtb1 =
new VirtTestBaseDrv;
I think the concept I am using here is polymorphism. I have done things like this many times when all the files are in the same project. Of course, the compiler throws an error because it doesnt know what VirtTestBaseDrv.
The question then is, how do I get it to know what it is
Could I perhaps GetProcAddress a function which creates an instance and then returns a pointer to it
At this point, I'd use COM. What this thread is describing is pretty much what a basic COM object is: 4 exported functions, all standard, and a class that implements the IUnknown interface.
So in the main program I would have an abstract base class defined as pure virtual and then in the plugin I would have an 'implementation', for lack of a better word, of the abstract base class. I would create a function to create an instance of the class and return a pointer to it in the plugin, this function would be accessed from the main program with GetProcAddress.
Would I just search for information on 'how to create a COM interface' I have little experience with using COM, could you recommend some resource web pages, perhaps with tutorials
You don't have to export the class if you just export a 2 functions that you can retrieve via GetProcAddress. One to create the class, and receiving a pointer, one to destroy the class. The interface should be plain virtual like COM. You don't need COm
class IMyInterface { public: virtual int DoThis(char*)=0; virtual void DoThat(int)=0; virtual void set_this(int); virtual void get_this()=0; };
You can even write a interface function that destroys the object.
This is the only way when you want to use and need to use LoadLibrary.
All stuff with declspec export/import needs a implicit load of the library and does not support explicit linking!
I am working on a plugin architecture that will hopefully work much like the one for 3DSMax.
It seems as if I will have to implement a series of base abstract classes which plugin developers can derive their plugin classes from writing the functions as appropriate in their plugins.
Once I have dynamically loaded a plugin, containing a class that is derived from one of the base classes defined in the main program, would I expect to be able to use that plugin class 'automatically' or am I missing a step
In practice, one would not want to do LoadLibrary on a class method.
In theory, it can be done if you know the mangled name of the class and you have an instance of that class to pass as the first argument to the result of GetProcAddress. But it makes no sense to go this route.
Just in case you're not overengineering your solution, you can implement a class in a DLL and export all its members by using __declspec(dllexport) on the whole class. But if you need version independence and see your objects as implementing interfaces, then COM is one route. (Search MSDN or the web for literature and examples).
If you are more open on technologies to use, consider using .NET for your component development. Relative to .NET, COM is old technology that should only be used if you must stick to older versions of Visual C++ (VC6) and VB6. If you go with .NET, then you can use C++/CLI (C++ with .NET extensions), C#, or VB.NET to develop your software.
To summarize, both COM and .NET pose a learning curve. But your time is better invested with .NET since its way more powerful, flexible, and easier to learn and use. The choice should be made based on compatibility concerns.
Using classes from dynamically linked DLL
Murthi
No! You can not use class exports via this way with LoadLibrary.
A simple approach is to create interfaces like COM interfaces and return only pointers to those interfaces from the DLL. This is alaso a very flexible aproach and you hide the implementation details fully.
Padmanabha
You're describing the concept of interfaces (which is an abstract base class). Interfaces don't have definitions, only prototypes. Hence they wouldn't be "defined in the main program."
COM objects don't support implementation inheritance. .NET objects, however do (but only single inheritance.)
G Balaji
ACK!
This is the most simple design, that hides every complexity inside the plugin and the way how the interface cooperates is simple enough too!
Thats the way COM works, if not working accross apartment boundaries or processes.
Now the last hint from me: Take care about the parameters you pass by the interface, don't use STL classes. Restrict yourself to the basic types and when needed use SafeArray or BSTR. Don't perform allocation and deallocations across modules, in other words: don't allocate memory in the add in and free it in the program, unless you use safe types like BSTRs or SafeArrays!
pwang
You can have an abstract class that can be seen in booth app and dll.
The abstract class should have a method virtual void Destroy() = 0;
An implement like this
void ClassImplementation::Destroy()
{
delete this;
}
Then export function from DLL like this
bool Create[Class]Instance(BaseClass **pInstance)
{
*pInstance = new ClassImplementation();
return true;
}
Then in your app you can call GetProcAddress with ("Create[Class]Instance").
Replace [Class] with your class name;
Sandy Gallagher
_John Reynolds_
Right off the bat, I just want to say thank you very much Brian. I think I have the general idea here and you are certainly helping me nail down the specifics.
I have created a prototype in my main program;
class
VirtTestBase{
protected
: int width, height;public
: void set_values (int , int ); void printarea (void); virtual int area (void) =0;VirtTestBase(
void);~VirtTestBase(
void);};
and also, the implementation
#include
"StdAfx.h"#include
".\virttestbase.h"#include
<windows.h>VirtTestBase::VirtTestBase(
void){
}
VirtTestBase::~VirtTestBase(
void){
}
void
VirtTestBase::set_values(int a, int b) {width=a;
height=b;
}
void
VirtTestBase::printarea(void) {CString message;
message.Format( "%d" ,
this->area() );MessageBox(NULL, message, "This message box brought to you by a VirtTestBase class instance.",MB_OK);
}
In my plugin I have create a class which is to inherit from this class defined in the main program with the definition
#pragma
once#include
"VirtTestBase.h"class
VirtTestBaseDrv: public VirtTestBase{
public
: int area (void);};
and the the implementation
#include
"StdAfx.h"#include
".\virttestbasedrv.h"int
VirtTestBaseDrv::area() { return (width * height);}
withing the main program I am attempting to use the class from the plugin by
VirtTestBase * vtb1 =
new VirtTestBaseDrv;I think the concept I am using here is polymorphism. I have done things like this many times when all the files are in the same project. Of course, the compiler throws an error because it doesnt know what VirtTestBaseDrv.
The question then is, how do I get it to know what it is
Could I perhaps GetProcAddress a function which creates an instance and then returns a pointer to it
Trupti
At this point, I'd use COM. What this thread is describing is pretty much what a basic COM object is: 4 exported functions, all standard, and a class that implements the IUnknown interface.
Brian
vbMark
So in the main program I would have an abstract base class defined as pure virtual and then in the plugin I would have an 'implementation', for lack of a better word, of the abstract base class. I would create a function to create an instance of the class and return a pointer to it in the plugin, this function would be accessed from the main program with GetProcAddress.
Correct
T. Ruffle
Martin,
Thank you for your quick response.
Would I just search for information on 'how to create a COM interface' I have little experience with using COM, could you recommend some resource web pages, perhaps with tutorials
Helge Shep
@Rmon:
You don't have to export the class if you just export a 2 functions that you can retrieve via GetProcAddress. One to create the class, and receiving a pointer, one to destroy the class. The interface should be plain virtual like COM. You don't need COm
class IMyInterface
{
public:
virtual int DoThis(char*)=0;
virtual void DoThat(int)=0;
virtual void set_this(int);
virtual void get_this()=0;
};
You can even write a interface function that destroys the object.
This is the only way when you want to use and need to use LoadLibrary.
All stuff with declspec export/import needs a implicit load of the library and does not support explicit linking!
Shawn de Wet
I am working on a plugin architecture that will hopefully work much like the one for 3DSMax.
It seems as if I will have to implement a series of base abstract classes which plugin developers can derive their plugin classes from writing the functions as appropriate in their plugins.
Once I have dynamically loaded a plugin, containing a class that is derived from one of the base classes defined in the main program, would I expect to be able to use that plugin class 'automatically' or am I missing a step
Damn
In practice, one would not want to do LoadLibrary on a class method.
In theory, it can be done if you know the mangled name of the class and you have an instance of that class to pass as the first argument to the result of GetProcAddress. But it makes no sense to go this route.
Just in case you're not overengineering your solution, you can implement a class in a DLL and export all its members by using __declspec(dllexport) on the whole class. But if you need version independence and see your objects as implementing interfaces, then COM is one route. (Search MSDN or the web for literature and examples).
If you are more open on technologies to use, consider using .NET for your component development. Relative to .NET, COM is old technology that should only be used if you must stick to older versions of Visual C++ (VC6) and VB6. If you go with .NET, then you can use C++/CLI (C++ with .NET extensions), C#, or VB.NET to develop your software.
To summarize, both COM and .NET pose a learning curve. But your time is better invested with .NET since its way more powerful, flexible, and easier to learn and use. The choice should be made based on compatibility concerns.
Brian
Santosh Thankachan
My plugin already knows what VirtTestBase is, I have simply put its header file in with the plugin.
The problem is in reverse, the main program does not know about VirtTestBaseDrv.