Dynamically Loading Platform Invoke DLLs

team lib

When constructing a Platform Invoke prototype, you specify the name of the DLL as the first parameter to the DllImport attribute, with no path information. The runtime will locate the DLL using the normal DLL location rules: look first in the current directory, and then in the System32 directory, and then along the path .

What if you want to choose the DLL to be used at run time? There are two distinct cases to be considered here, depending on whether you want to specify the path to the DLL named in the Platform Invoke prototype or make a completely dynamic choice of DLL.

Choosing the Path to the DLL at Run Time

The key here is the fact that if a suitably named DLL is already loaded when the external function is executed, Platform Invoke will use the loaded DLL to resolve references. So if you arrange to load the DLL you require before calling a function using Platform Invoke, your chosen DLL will be used rather than another DLL being loaded.

There isnt a method in the .NET Framework for dynamically loading a Windows DLL, so you have to use the LoadLibrary Windows API call, which lives in Kernel32.dll. Because this is itself a Windows API call, you need to construct a Platform Invoke prototype for LoadLibrary before you can use it. Listing 13-2 is a managed C++ sample program that shows this technique in use. You can find the source for this program in the Chapter13\CppLoadLib folder in the books companion content.

Listing 13-2: CppLoadLib.cpp
start example
 #include "stdafx.h" #using<mscorlib.dll> usingnamespaceSystem; usingnamespaceSystem::Runtime::InteropServices; usingnamespaceSystem::Text; //ThePlatformInvokeprototypeforLoadLibrary [DllImport("kernel32.dll",CharSet=CharSet::Auto,SetLastError=true)] extern "C" void*LoadLibrary([MarshalAs(UnmanagedType::LPTStr)]String*pLibName); //FlagforusewithFormatMessage constintFORMAT_MESSAGE_FROM_SYSTEM=0x00001000; //ThePlatformInvokeprototypeforFormatMessage [DllImport("kernel32.dll",CharSet=CharSet::Auto)] extern "C" intFormatMessage(intflags, void*source,intmessageId, intlangId,StringBuilder*buff, intsize,void*args); //TheDLLtobeloadediscalledTestDll.dll,butIwantto //specifythepathatruntime...itisn'tinanyofthestandard //places [DllImport("testdll.dll",CharSet=CharSet::Auto)] extern "C" longSquare(shortnVal); voidmain() { //LoadtheDLL //Ifthereisanerror,displaythemessage if(pLib==0) { intnErrCode=Marshal::GetLastWin32Error(); StringBuilder*pBuff=newStringBuilder(256); FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, 0,nErrCode,0, pBuff,pBuff->Capacity,0); Console::WriteLine("ErrorfromLoadLibrary:{0}", pBuff->ToString()); return; } Console::WriteLine("LibraryloadedOK"); //Calltheunmanagedfunction longlRes=Square(5); Console::WriteLine("Squareof5is{0}",__box(lRes)); } 
end example
 

The LoadLibrary function takes as its only argument a string containing the path to the DLL to be loaded. If the function succeeds, the return value is a handle to the loaded library, which is represented as a void* pointer; a value of zero indicates the function has failed to load the library. If an error occurs, the GetLastWin32Error and FormatMessage functions can be used to retrieve the error code and convert it to a message. Once the DLL has been loaded, the Platform Invoke call will use the loaded DLL rather than looking for another one.

One drawback of this method is that the DLL you load must have the same name as the one specified in the Platform Invoke prototype. Because the DLL name must be known at compile time, you cannot use a variable to provide the information at run time.

Fully Dynamic DLL Loading

On occasion, you might need to execute an unmanaged function in a DLL in a completely dynamic manner. Some plug-in architectures allow users to specify a DLL and function to use at run time, so you cannot specify the name of the DLL in a predefined Platform Invoke prototype.

You can, in these situations, load a DLL in a fully dynamic manner by using a .NET Framework feature called reflection emit . This advanced feature is used by compiler and tool writers; it provides a way to generate IL code on the fly at run time and either save it to disk or execute it. Reflection emit can be used to create assemblies, modules, and types and is too complex a topic to cover here.

 
team lib


COM Programming with Microsoft .NET
COM Programming with Microsoft .NET
ISBN: 0735618755
EAN: 2147483647
Year: 2006
Pages: 140

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net