Dynamically loading classes from DLLs
-->
Have you ever wondered whether there is a way to have an application extrinsically load a DLL (e.g. via the LoadLibrary() function) which exports classes so that the loader of the DLL can then use objects of the class ?
This is basically no problem, the only thing that makes this a pain in the [censored] are the 'C++ mangled names' of the methods in the DLL's export section (e.g. '?CreateObject@CFrameDoc@@SGPAVCObject@@XZ'). The simple trick get around this (and not using (D)COM) is: If you have (e.g.) a class called CMyClass, declare it in the header file common to both application and DLL:
#include ...
#ifdef _DLL // assume this is defined when we build the DLL
#define _DYNLINK __declspec( dllexport)
#else
#define _DYNLINK __declspec( dllimport)
#endif
class _DYNLINK CMyClass
{
public:
CMyClass ();
virtual ~CMyClass();
void DoSomethingUseful();
};
then, export a function from the DLL that returns a pointer to an instance of CMyClass, let's call it 'CreateMyClass()' - it basically should do 'return ( new CMyClass());'
#ifndef _DLL
typedef CMyClass* ( *PFNCREATEMYCLASS)();
#else
_DYNLINK CMyClass* CreateMyClass()
{
return ( new CMyClass());
}
#endif
Also provide a function from the DLL that performs a 'delete' on the object. Let's call it 'DeleteMyClass()' - it basically should do 'delete pObj;'. This function is necessary due to the fact that the CRT uses different heaps and therefore different allocators for EXEs/DLLs, so that you're just lucky if there's no crash...
#ifndef _DLL
typedef void ( *PFNDELETEMYCLASS)( CMyClass*);
#else
_DYNLINK void DeleteMyClass ( CMyClass* pObj)
{
delete pObj;
}
#endif
Last but not least, we need a way to get access to the objects methods without 'knowing' about the source code:
typedef void ( CMyClass::*PMYCLASSMETHOD)();
// the type created above ALWAYS points to a memer function of class 'CMyClass'
// which takes no arguments and returns nothing
#ifndef _DLL
typedef PMYCLASSMETHOD ( *PFNGETCLASSMETHOD)();
#else
_DYNLINK PMYCLASSMETHOD GetClassMethod ()
{
return &CMyClass::DoSomethingUseful;
}
#endif
We also need a module definition file for our DLL. Remember: We use a C interface to our DLL! (the 'PRIVATE' keyword instructs the linker not to list the function in the DLL's import library).
LIBRARY dynclass.dll
EXPORTS
CreateMyClass @2 PRIVATE ; object creation
DeleteMyClass @3 PRIVATE ; object destruction
GetClassMethod @4 PRIVATE ; method access
In your application, load the DLL and get a pointer to 'CreateMyClass()' (error checking omitted for brevity)
PFNCREATEMYCLASS pfnCreateMyClass; PFNDELETEMYCLASS pfnDeleteMyClass; PFNGETCLASSMETHOD pfnGetClassMethod; PMYCLASSMETHOD pDoSomethingUseful; CMyClass* pMyClass; HANDLE hDll; hDll = LoadLibrary ( ...); pfnCreateMyClass = (PFNCREATEMYCLASS) GetProcAddress ( hDll, "CreateMyClass"); pfnDeleteMyClass = (PFNDELETEMYCLASS) GetProcAddress ( hDll, "DeleteMyClass"); pfnGetClassMethod = (PFNGETCLASSMETHOD) GetProcAddress ( hDll, "GetClassMethod"); // et voila - an instance of CMyClass! pMyClass = ( pfnCreateMyClass) (); pDoSomethingUseful = ( pfnGetClassMethod ()); ( pMyClass->*pDoSomethingUseful) (); ( pfnDeleteMyClass ( pMyClass));
Outlook: This article just intends to demonstrate the technology 'how to do it'. There's much work to do if you want to use it in your applications, e.g. creating just one function in the DLL that fills in a structure which holds all the function pointers you need, or even a proxy class that does this automatically. Well, i'll keep this for a future update of this article.

Comments
Edit SYS
Posted by Legacy on 12/20/2002 12:00amOriginally posted by: Daniel
ReplyHelp - Global Hooks - win api
Posted by Legacy on 03/11/2002 12:00amOriginally posted by: Sugavaneswaran
We are developing a tool in Visual Basic 6, It takes a Visual Basic 6 user application (in the sense some visual basic executable specified by a user, given the path). This Executable is loaded into our Tool.
This looks like parent and child relationship, Our tool will be the Parent and user executable becomes child form in our tool. We do this by using “SetParent” API.
Now if a button is clicked on the user application (which is a executable developed by user, we can’t modify its code) it invokes a form (Ordinary Form) whose parent will be the Screen. We want our tool to be the parent of this form instead of the screen.
For this we use Global Hook. We capture WM_CREATE message and change the forms parent from Screen to our Tool.
In Local Hook we are able to capture this but when we make a global hook it is not working for us. We have to keep it as global hook because our tool runs in one process and User executable is another process.
I am here with attaching the VB code and global DLL (Done in VC++) for your reference.
Any help regarding how to access a Callback function in DLL is highly appreciated.
ReplyHow can I use CHECKLIST_ACLUI class (windows security properties)
Posted by Legacy on 01/24/2002 12:00amOriginally posted by: Lee D
I tried using CreateWindow with the CHECKLIST_ACLUI class (I used Spy++ to see what the class name was). This doesn't seem to work. Perhaps CHECKLIST_ACLUI is not aa System Global class but is instead an Application Global class of Windows Explorer? In that case maybe I have to load some dll first so that I can use the class? Any help would be appreciated.
ReplyHow to find out signatures of dll methods when its not mine ?
Posted by Legacy on 02/08/2001 12:00amOriginally posted by: Harshad
If dll is not being written by me & someone else, how do I extract info about dll ie. the classname, methods exported, their signatures and so on? Or in other terms how to use a dll which is available to me just as a dll file & nothing else is know about it ?
ReplyThere is a problem however
Posted by Legacy on 03/26/1999 12:00amOriginally posted by: Alon Albert
Both these solutions have problem.
What if the dll is not in my control (third party)?
The first solution has a simple workaround, just create a wrapper dll that implements said functions.
However, I do not like the solution very much because the code looks horrible and unintuitve.
The second solution is very elegant but will simply not work if the dll is third party code.
Is their any elegant way to resolve this issue?
ReplyAnother Easier Way of Dynamically Exporting Classes
Posted by Legacy on 12/21/1998 12:00amOriginally posted by: V. Rama Krishna
Reply