Dynamically loading classes from DLLs

ProXima Engineering Office -->

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.

Download demo project - 7KB



Comments

  • Edit SYS

    Posted by Legacy on 12/20/2002 12:00am

    Originally posted by: Daniel

    How can I edit the *.sys files?
    

    Reply
  • Help - Global Hooks - win api

    Posted by Legacy on 03/11/2002 12:00am

    Originally 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.

    Reply
  • How can I use CHECKLIST_ACLUI class (windows security properties)

    Posted by Legacy on 01/24/2002 12:00am

    Originally 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.

    Reply
  • How to find out signatures of dll methods when its not mine ?

    Posted by Legacy on 02/08/2001 12:00am

    Originally 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 ?

    Reply
  • There is a problem however

    Posted by Legacy on 03/26/1999 12:00am

    Originally 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?

    Reply
  • Another Easier Way of Dynamically Exporting Classes

    Posted by Legacy on 12/21/1998 12:00am

    Originally posted by: V. Rama Krishna

    The way COM interface pointers are obtained from a server can be used to dynamically export classes. The
    trick is to declare the class as pure virtual in the client EXE and define the implementation of the
    functions in the DLL.
    
    

    e.g.

    In the Exe and DLL

    class CExportedClass
    {
    virtual void func1() = 0;
    virtual void func2() = 0;
    int a;
    }

    //In DLL
    class CExportedClassImpl : public CExportedClass
    {
    virtual void func1() { ... }
    virtual void func2() { ... }
    int a;
    }

    EXPORTFNTYPE CExportedClass* GetExportClass()
    {
    return new CExportedClassImpl();
    }

    //In exe
    //Get the pointer to ExportClass fn.
    //

    CExportedClass* expC = GetExportClass();

    expC->func1();
    expC->func2();

    delete expC;

    How is this?

    Reply
Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • IBM Worklight is a mobile application development platform that lets you extend your business to mobile devices. It is designed to provide an open, comprehensive platform to build, run and manage HTML5, hybrid and native mobile apps.

  • In this webinar, IDC featured speaker Steve Conway, Vice President of High Performance Computing, will present an update on the global x86 HPC cluster market. The presentation will include IDC's five-year forecast for the medium- to large-scale technical computing and data analysis emerging markets by systems, processors and application middleware. Cray's featured speaker, John Lee, Vice President of Cray Cluster Advanced Technology Systems, will present the new Cray® CS400™ cluster series based on …

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds