[[DLLImport("DLL file ")]
Modifier extern returns the variable type method name (parameter list)
These include:
DLL file: a library file containing external methods.
Modifier: Access modifier, which can be used when declaring methods other than abstract.
Return variable type: In the DLL file, you need to call the return variable type of the method.
Method name: the name of the method you need to call in the DLL file.
Parameter list: list of methods that need to be called in the DLL file.
Note: The system is required. The Runtime.InteropServices namespace in the program declaration.
DllImport can only be placed on a method declaration.
The DLL file must be located in the current directory of the program or in the system-defined query Path (that is, the path set in the system environment variable PATH).
The return variable type, method name and parameter list must be consistent with the definitions in the DLL file.
To use another function name, you can use the EntryPoint property setting, for example:
[DllImport("user32.dll ",EntryPoint="MessageBoxA")]
Static extern int MsgBox(int hWnd, string msg, string caption, int type);
Other optional DllImportAttribute attributes:
CharSet represents the character set used in the entry point, for example, CharSet=CharSet. Ansi;
SetLastError indicates whether the method retains the "last error" of Win32, for example, SetLastError = true;;
ExactSpelling indicates whether the EntryPoint must exactly match the spelling of the indicated entry point, for example, ExactSpelling=false. ;
PreserveSig indicates whether the signature of the method should be preserved or transformed, for example: PreserveSig = true;;
CallingConvention represents the calling convention of the entry point, such as: calling convention = calling convention.winapi;
In addition, please refer to some other articles about "data marshaling" and "marshaling numbers and logical scalars" [2].
C# example:
1. Start VS.NET and create a new project named "Tzb" with "Windows Application" as the template.
2. Double-click the Button item in the Windows Forms item in the toolbox to add a button to the form 1.
3. Change the properties of the button: the name is "B 1" and the text is "Call DllImport to pop up a prompt box". Adjust the button B 1 to a suitable size and move it to a suitable position.
4. Double-click "Form 1" in the class view to open the code view of "Form 1.cs" and enter "Use System". The runtime.interop service is on the "namespace Tzb". Import namespaces.
5. Double-click the button b 1 in Table1. CS "view, declare the method" MsgBox "with keywords static and extern above the" B 1_Click "method, and attach the DllImport property to the method. We're going to use "user32.dll" here.
[DllImport("user32.dll ",EntryPoint="MessageBoxA")]
Static extern int MsgBox(int hWnd, string msg, string caption, int type);
Then add the following code in the "B 1_Click" method body to call the method "MsgBox":
MsgBox(0, "This is the prompt box that pops up when calling DllImport!" , "Challenge Cup", 0x30);
6. Press F5 to run the program, and click B 1 to pop up the following prompt box:
(2) Dynamically load and call unmanaged functions in DLL.
It has been explained above how to use DllImport to call an unmanaged function in a DLL, but this is a global function. If the unmanaged function in the DLL has a static variable S, the static variable S will be automatically added with 1 every time this function is called. As a result, when it is necessary to re-count, the desired result cannot be obtained. The following will be illustrated by examples:
Create 1. DLL
1) Start Visual c++ 6.0;; ;
2) Create a new project named "Win32 dynamic link library";
3) Select "A Simple dll Project" in the Dll Category selection interface;
4) Open Count.cpp and add the following code:
//Export function, which is called by "_stdcall" standard.
extern " C " _ declspec(dll export)int _ stdcall count(int init);
Int _stdcall count (int init)
The {//count function initializes the static plastic variable S with the parameter init, so that S returns the value after adding 1
static int S = init
s++;
Return to s;
}
5) Press "F7" to compile and get Count.dll (in the debugging folder under the project directory).
2. Call the count function in DLL with DllImport.
1) opens the project "Tzb" and adds a button to the "Form 1" form.
2) Change the property of the button: the name is "B2" and the text is "Call the counting function in DllImport". Adjust the button B 1 to a suitable size and move it to a suitable position.
3) Open the code view of "Form 1.cs", and declare the method "count" with keywords static and extern, so that it has the realization of exporting the function count from Count.dll. The code is as follows:
[DllImport("Count.dll")]
Static external integer counting (integer initialization);
4) in the "form 1" view, double-click the button B2. CS ",and add the following code in the body of the" B2_Click "method:
MessageBox。 Show ("calls the count function in DllImport, the passed-in parameter is 0, and the result is" +count(0). ToString (), "Challenge Cup");
MessageBox。 Show ("Call the count function in DllImport, the passed-in parameter is 10, and the result is:" +count (10). Tostring ()+"nThe result is not expected 1 1! ! ! " , "Challenge Cup");
MessageBox。 Show ("The result shows that calling unmanaged n function in DllImport is a global static function! ! ! " , "Challenge Cup");
5) Copy Count.dll to the binDebug folder of the project "Tzb", press "F5" to run the program, and click the B2 button to pop up the following three prompt boxes:
The prompt box 1 shows the result of calling "count(0)", and the second prompt box shows the result of calling "count( 10)", which proves that "calling unmanaged function in DllImport is a global static function". So, sometimes we can't achieve our goal, so we need to use the following methods: C# dynamically calls the functions in the DLL.
3.C# dynamically calls functions in DLL
Because using DllImport in C# can't be like dynamically loading/unloading assembly, you can only use API functions. In kernel32.dll, the functions related to dynamic library call include [3]:
①LoadLibrary (or AfxLoadLibrary of MFC) loads the dynamic library.
②GetProcAddress, to obtain the function to be introduced and convert the symbol name or identification number into the internal address of the DLL.
③FreeLibrary (or AfxFreeLibrary of MFC), and release the dynamic link library.
Their prototype is:
h module LoadLibrary(LPCTSTR lpFileName);
FARPROC GetProcAddress(HMODULE HMODULE,LPCWSTR lpProcName);
BOOL free library(HMODULE HMODULE);
Now, we can use intptrhmodule = loadlibrary ("count. dll"); To get the handle to the Dll, use intptr farproc = getprocaddress (hmodule, "_ count @ 4"); Gets the entry address of the function.
However, after knowing the entry address of the function, how to call this function? Because there is no function pointer in C#, and there is no function pointer to call methods like C++, we have to use other methods. Through research, it is found that we can achieve our goal by combining classes and functions in the system. Reflection.Emit and System.Reflection.Assembly. For the convenience of future use and code reuse, we can write a class.
1) dld class writing:
1. Open the project Tzb, open the class view, right-click Tzb, select Add-Class, and set the class name to dld, that is, dynamically load the first letter of each word in the dll.
2. Add the required namespaces and declare the enumeration of parameter passing methods:
Use the system. This namespace is required by runtime. interopservicesdlllimport.
Use the system. Reflection; //This namespace is required to use the Assembly class.
Use the system. Reflection. Launch; //This namespace is required to use ILGenerator.
Add the following code above the "public class dld" to declare the enumeration of parameter passing methods:
///Summary
///Enumerates parameter passing methods, where ByValue means value passing and ByRef means address passing.
////Summary
Public enumeration mode pass
{
ByValue = 0x000 1,
ByRef = 0x0002
}
3. Declare LoadLibrary, GetProcAddress, FreeLibrary and private variables hModule and farProc:
///Summary
///The prototype is: Hmodule LoadLibrary (lpctstr lpfilename);
////Summary
///param name="lpFileName"DLL file name /param
///Returns the handle of the library module///Returns
[DllImport("kernel32.dll")]
Static extern IntPtr LoadLibrary (string lpfilename);
///Summary
///The prototype is: farproc getprocaddress (hmodule hmodule, lpcwstr lpprocname);
////Summary
///param name="hModule "contains the handle of the function library module to be called /param.
///param name="lpProcName "name of calling function /param
///Return function pointer/Return
[DllImport("kernel32.dll")]
Static extern intptr getprocaddress (intptrhmodule, string LP procname);
///Summary
///The prototype is Bool Free Library (HMODULE HMODULE);
////Summary
///param name="hModule "Handle of function library module to be released /param
/// returns has released the specified Dll/returns?
[DllImport("kernel32 ",EntryPoint="FreeLibrary ",SetLastError=true)]
Static Extern Bool Free Library (INTPTR HMODULE);
///Summary
///Handle of function library module returned by LoadLibrary
///Summary
private IntPtr hModule=IntPtr。 Zero;
///Summary
///Function pointer returned by getProcAddress
///Summary
private IntPtr farProc=IntPtr。 Zero;
4. Add the LoadDll method, and overload this method for the convenience of calling:
///Summary
///Load Dll
///Summary
///param name="lpFileName"DLL file name /param
Public void LoadDll (string lpFileName)
{
hm odule = LoadLibrary(LP filename);
if(hModule==IntPtr。 Zero)
Throw (new exception ("not found:" +lpFileName+ ")." ));
}
If you already have the handle to the loaded Dll, you can use the second version of the LoadDll method:
Public void LoadDll(IntPtr HMODULE)
{
if(HMODULE==IntPtr。 Zero)
Throw(new Exception ("The handle of the passed-in function library HMODULE is empty." ));
hModule = HMODULE
}
5. Add the LoadFun method and overload it to make it easy to call. The specific code and comments of the method are as follows:
///Summary
///Get function pointer
////Summary
///param name="lpProcName "name of calling function /param
Public void LoadFun (string lpProcName)
{//If the handle of the function library module is empty, an exception is thrown.
if(hModule==IntPtr。 Zero)
Thrown (new exception ("the handle of the function library module is empty, please ensure that the operation of LoadDll has been performed!") ));
//Get function pointer
farProc = GetProcAddress(hModule,lpProcName);
//If the function pointer, throw an exception.
if(farProc==IntPtr。 Zero)
Throw(new Exception ("not found:" +lpProcName+ "entry point of this function"));
}
///Summary
///Get function pointer
////Summary
///param name="lpFileName "contains the DLL file name of the function to be called /param.
///param name="lpProcName "name of calling function /param
Public void LoadFun (string lpFileName, string lpProcName)
{//Get the handle of the function library module.
hm odule = LoadLibrary(LP filename);
//If the handle of the function library module is empty, an exception is thrown.
if(hModule==IntPtr。 Zero)
Throw (new exception ("not found:" +lpFileName+ ")." ));
//Get function pointer
farProc = GetProcAddress(hModule,lpProcName);
//If the function pointer, throw an exception.
if(farProc==IntPtr。 Zero)
Throw(new Exception ("not found:" +lpProcName+ "entry point of this function"));
}
6. Add the UnLoadDll and Invoke method, which is also overloaded:
///Summary
///uninstall the Dll
////Summary
Public void UnLoadDll ()
{
free library(hModule);
hModule=IntPtr。 Zero;
farProc=IntPtr。 Zero;
}