let's talk about the points for attention when calling DLL by c#
First, you need to know what is managed and what is unmanaged. Generally speaking, unmanaged code is mainly a component of DLL and activeX developed on win
32 platform, and managed code is developed on. net platform.
(1) General methods of calling unmanaged functions in DLLs
First, external methods should be declared in the source program of C# language, and the basic form is as follows:
[DLlimport ("DLL file")] modifier extern returns the name (parameter list) of variable type methods
where:
DLL file: a library file containing external methods.
modifier: access modifier, which can be used when declaring methods except abstract.
return variable type: you need to call the return variable type of the method in the DLL file.
method name: the name of the method you need to call in the DLL file.
parameter list: the list of methods you need to call in the DLL file.
note: you need to use the System.Runtime.InteropServices namespace in the procedure 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 query Path defined by the system (that is, the path set by path in the system environment variable).
the return variable type, method name and parameter list must be consistent with the definitions in the DLL file.
to use other function names, you can use the EntryPoint property setting, such as:
[DllImport("user32.dll ", EntryPoint="MessageBoxA")]
static extern int MsgBox(int hWnd, string msg, string caption, int type);
Other optional DllImportAttribute attributes:
CharSet indicates the character set used in the entry point, such as CharSet=CharSet.Ansi;;
SetLastError indicates whether the method retains the Win32 "last error", 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 converted, for example, PreserveSig=true;;
CallingConvention indicates the calling convention of the entry point, such as: calling convention = calling convention.winapi;
in addition, please refer to other articles about "data marshaling" and "marshaling numbers and logical scalars".
Examples of C # operation:
1. Start VS.NET, create a new project with the project name "Tzb" and the template "Windows Application";
2. Double-click the Button item in the Windows Forms item in the Toolbox to add a button to the Form1 form;
3. Change the properties of the button: the Name is "B1" and the Text is "Call DllImport to pop up a prompt box", and adjust the button B1 to an appropriate size and move it to an appropriate position;
4. double-click "Form1" in the class view to open the code view of "Form1.cs" and enter "using system. runtime.interop services;" on "namespace Tzb". To import the namespace;
5. double-click the button B1 in the "Form1.cs[ [design]" view, use the keyword static and
extern to declare the method "MsgBox" on the "B1_Click" method, and attach the DllImport property to the method. Here we are going to use the "MessageBoxA" function in "user32.dll". The specific code is as follows:
[dllimport ("user32.dll", entrypoint = "messageboxa")]
static extern int msgbox (inthwnd, stringmsg, stringcaption, int type);
then add the following code in the body of the "B1_Click" method to call the method "msgbox":
msgbox (, "This is the prompt box for calling DLL with DllImport!" , "Challenge Cup", x3);
6. press "F5" to run the program, and then click the button B1.
(2) dynamically loading and calling the unmanaged function in the DLL
It has been explained above how to call the unmanaged function in the DLL with DllImport, 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 incremented 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 with examples:
1. Creation of dll
1) Start Visual C++ 6.;;
2) create a new "Win32 Dynamic-Link Library" project with the name "count";
3) select "a simple dll project" in the "Dll kind" selection interface;
4) open Count.cpp, and add the following code:
// Export function, and call
extern "c" _ declspec (DLLExport) int _ stdcallcount (intinit) using "_ stdcallstandard";
int _ stdcallcount (intinit)
{//count function, which uses the parameter init to initialize the static plastic variable s, and returns the value after adding 1 to s
static int S=init;
S++;
return S;
}
5) Press "F7" to compile and get Count.dll (in the Debug folder under the project directory).
2. Call the count function in the DLL with DllImport
1) Open the project "Tzb" and add a button to the Form1 form.
2) change the properties of the button: the Name is "B2" and the Text is "Call the count function in DllImport", and adjust the button B1 to an appropriate size and move it to an appropriate position.
3) open the code view of "Form1.cs", declare the method "count" with keywords static and extern, and make it have the implementation of the export function count from Count.dll. The code is as follows:
[DLlimport ("count. dll")]
Static extern int count (int init);
4) double-click the button B2 in the "Form1.cs[ [design]" view, and add the following code in the body of the "B2_Click" method:
MessageBox.Show ("Call the count function in the DLL with DllImport, and the passed-in argument is , and the result is:" +count().ToString ().
MessageBox.Show ("Call the count function in DllImport, n the passed-in argument is 1, and the result is:"+count (1). tostring ()+"nThe result is not the expected 11! ! ! " , "Challenge Cup");
MessageBox.Show ("The result shows that calling unmanaged n function in DllImport is a global and 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 button B2 to pop up the following three prompt boxes.
the first prompt box shows the result of calling "count()" and the second prompt box shows the result of calling "count(1)", which proves that "calling unmanaged functions in DllImport is a global and static function". So, sometimes we can't achieve our goal, so we need to use the following method: C# dynamically calls the function in the
DLL.
3. C# dynamically calls the function in DLL
Because DllImport used in C# can't be like dynamic load/unload assembly, we can only use API functions. In kernel32.dll, the functions related to dynamic library call include [3]:
1) LoadLibrary (or AfxLoadLibrary of MFC) to load dynamic library;
2) GetProcAddress, which obtains the function to be introduced and converts the symbol name or identification number into the internal address of the DLL;
3) FreeLibrary (or AfxFreeLibrary of MFC), and release the dynamic link library.
their prototypes are:
hmodule load library (lpctstr lpfilename);
FARPROC GetProcAddress(HMODULE hModule, LPCWSTR lpProcName);
BOOL FreeLibrary(HMODULE hModule);
now, we can use intptr Count.dll = loadlibrary; To get the handle of the Dll, use intptrfarproc = getprocaddress (hmodule, "_ count @ 4"); To get the entry address of the function.
however, how to call this function after knowing its entry address? Because there is no function pointer in C#, there is no function pointer calling method like C++, so we have to use other methods. Through research, it is found that we can achieve our goal by combining the classes and functions in System.Reflection.Emit and System.Reflection.Assembly. For the convenience of future use and code reuse, we can write a class.
1. Open the project Tzb, open the class view, right-click Tzb and select Add --> "Class", the class name is set to "dld", that is, the initial letter of each word of dynamic loading dll;
2. Add the required namespaces and enumerate the delivery methods of declaration parameters:
usingsystem. runtime.interopservices; //DllImport requires this namespace
using System.Reflection; //this namespace is required to use the Assembly class
using System.Reflection.Emit; //To use ILGenerator, you need to use this namespace
to add the following code to "public class dld" to declare the enumeration of parameter transfer methods:
//<; summary>
/// Enumeration of parameter transfer methods, with ByValue indicating value transfer and ByRef indicating address transfer < p