|
|
|
|
As if building things wasn't hard enough - you can still get into all kinds of trouble just trying to link things together. There are three types of link operation - there's a static link, dynamic link and then there's the thing you get when you do a LoadLibrary/GetProcAddress. LoadLibrary/GetProcAddressThe first hurdle to be surmounted is to export the function from its DLL. Here's an example. Let's assume that we want to gain access to a routine that takes two input integers and returns a pointer to a newly constructed object of some sort. In the DLL, we declare something to this effect:
extern "C" __declspec(dllexport) CObj* __cdecl
MakeNewObj( int iArg1, int iArg2)
{ return new CObj( iArg1, iArg2 ); } The extern "C" is required to stop the C++ compiler from decorating the name of the exprorted function. The __declspec(dllexport) will make the function available externally. Use of this makes an entry in the DEF file unneccessary. The __cdecl defines the functions calling type as standard C. The alternative would have been PASCAL type. The difference between the two is the order in which arguments are passed on the stack and who is responsible for stack clean up. In PASCAL, the callee balances the stack before returning. In __cdecl, the caller balances the stack after the called function returns. On the caller side, we need a variable to contain the function pointer and need some way to declare a variable of the correct type. The normal way to to construct a typedef that will do the trick for us.
typedef CObj* (WINAPIV* PROCGETOBJ)( int, int);
We will also need to load the library in order to gain access to the proc address.
HMODULE hLib = LoadLibrary( _T("MyModule.dll") );
if ( hLib ) { PROCGETOBJ pProcGetObj = (PROCGETOBJ)GetProcAddress( hLib, "MakeNewObj" ); if ( pProcGetObj ) { // do some stuff with the function pointer. } // If we loaded the library, then we have to unload it. FreeLibrary( hLib ); } |
|
|