转帖:Dynamically loading a class from a dll

Original Article on codegear.com
Create the class dll:

1. Create a virtual base class that contains all of the methods you would need to call from the class. This will be the interface your dll class will support.
2. Make the dll class derive from that interface.
3. Include the interface definition in the executable that will use the dll class.
4. Export a function from the dll that will create a new instance of the dll class and return it’s address (I will call this function CreateClassInstance()).

To use the class in your executable:

1. Call LoadLibrary() on the dll that contains the class.
2. Call GetProcAddress() to gain access to the CreateClassInstance() function.
3. Call CreateClassObject() and store the returned address in an interface pointer.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
/*
 
This example consists of two projects and six source files:
	header files:
	"FooInterface.h" -- definition for IFoo, the base class/interface
	"FooClass.h" -- definition for FooClass, deriving from IFoo
	"DllExports.h" -- dll's exported functions
 
	dll project:
	"DllMain.cpp" -- main cpp file for the dll project
	"FooClass.cpp" -- contains implementation for FooClass
 
	exe project:
	"ExeMain.cpp" -- main cpp file for exe project	
 
*/
 
 
//-------- FooInterface.h --------//
#ifndef FOOINTERFACE_H
#define FOOINTERFACE_H
 
class IFoo
{
public:
	int GetNumber() = 0;
	void SetNumber( int & ) =0;
};
 
#endif	// FOOINTERFACE_H

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//-------- FooClass.h --------//
#ifndef FOOCLASS_H
#define FOOCLASS_H
 
#include "FooInterface.h"
 
class FooClass :public IFoo
{
public:
	FooClass();
	const int& GetNumber();
	void SetNumber( int & );
private:
	int number;
};
 
#endif 	// FOOCLASS_H
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//-------- FooClass.cpp --------//
 
FooClass::FooClass()
{
	number = 0;
}
 
int FooClass::GetNumber()
{
	return number;
}
 
void FooClass::SetNumber(int &arg)
{
	number = arg;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
//-------- DllExports.h --------//
#ifndef DLLEXPORTS_H
#defind DLLEXPORTS_H
 
#ifdef __dll__
#define IMPEXP __declspec(dllexport)
#else
#define IMPEXP __declspec(dllimport)
#endif 	// __dll__
 
#include "FooClass.h"
 
 
extern "C"
void* IMPEXP CreateFooClassInstance();
 
 
#endif	// DLLEXPORTS_H
1
2
3
4
5
6
7
8
9
10
11
12
13
//-------- DllMain.cpp --------//
#define __dll__
#include "DllExports.h"
 
int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void*)
{
        return 1;
}
 
void* IMPEXP CreateFooClassInstance();
{
	return static_cast< void* > (new FooClass);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
//-------- ExeMain.cpp --------//
#include "FooInterface.h"
#include <windows.h>
#include <iostream.h>
#include <conio.h>
 
 
int main(int argc, char* argv[])
{
	HINSTANCE hdll = NULL;
	IFoo* piFoo = NULL;
	typedef void* (*pvFunctv)();
	pvFunctv CreateFoo;
 
 
	hdll = LoadLibrary("DllMain.dll");		// load the dll
	CreateFoo = static_cast < fpFunctv> (		// get the function pointer
		GetProcAddress( hdll, "_CreateFooClassInstance" ) );
 
	piFoo = static_cast< piFoo* > ( CreateFoo() );	// get pointer to object
 
	piFoo-&gtSetNumber(8);				// start using the object
	cout 	<< "Foo::number is epual to: "
		<< piFoo-> GetNumber()
		<< endl;
 
	cout	<< "Enter new value for Foo::number: ";
	int temp;
	cin	>> temp;
	piFoo-> SetNumber(temp);
	cout	<< "Foo::number is now: "
		<< piFoo-&gtGetNumber()
		<< endl;
	getch();
	delete piFoo = NULL;				// delete the object
	FreeLibrary(hdll);				// free the dll
}

There are a few interesting points in this piece of code.
1. The use of static_cast isn’t exactly correct.
2. The code is based on win32 API only.
3. The class layout is different from the way that VS2005 generates.
Hopefully I’ll make a updated version on this tutorial.

But many thanks to the author Vincent Drake

0 Responses to “转帖:Dynamically loading a class from a dll”


  1. No Comments

Leave a Reply