C # Call the DLL Method

Source: Internet
Author: User
Tags button attributes emit

(1) General method for calling unmanaged functions in DLL

First, the external method should be declared in the C # language source program. The basic form is:

[DllimpORT ("DLL file")]

Modifier extern return variable type method name (parameter list)

Where:

DLL file: contains the library file that defines external methods.

Modifier: access modifier, which can be used in addition to abstract when declaring a method.

Return variable type: In the DLL file, you need to call the return variable type of the method.

Method Name: name of the method to be called in the DLL file.

Parameter List: list of methods to be called in the DLL file.

Note: The system. runtime. interopservices namespace must be used in the program declaration.

DllimpORT can only be placed on the method declaration.

The DLL file must be located in the current program directory or the system-defined query path (that is, the path set by path in the system environment variable ).

The returned variable type, method name, and parameter list must be consistent with the definition in the DLL file.

To use other function names, you can use the entrypoint attribute settings, such:

[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, for example, charset = charset. ANSI;

Setlasterror indicates whether the method retains Win32 "previous error", for example, setlasterror = true;

Exactspelling indicates whether entrypoint must exactly match the spelling of the indicated entry point, for example, exactspelling = false;

Preservesig indicates whether the method signature should be retained or converted, for example, preservesig = true;

Callingconvention indicates the call convention of the entry point, for example: callingconvention = callingconvention. winapi;

For more information about "data sending and writing" and "sending numbers and logical scalar", see [2].

C # example:

1. Start vs. NET and create a new project named "TZB". The template is "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 button attributes: name is "B1", text is "dllimp"ORT calls the DLL pop-up prompt box, and adjusts the button B1 to the appropriate size, move to the appropriate location.

4. double-click "form1" in the Class View, open the "form1.cs" Code view, and enter "using system" on "namespace TZB. runtime. interopservices; "to import the namespace.

5. In the "form1.cs [design]" view, double-click the button B1 and use the keyword static and extern to declare the method "msgbox" on the "b1_click" method to convert the dllimpThe ORT attribute is appended to this method. Here we want to use the "messageboxa" function in "user32.dll". The specific code is as follows:
[DllimpORT ("user32.dll", entrypoint = "messageboxa")]

Static extern int msgbox (INT hwnd, string MSG, string caption, int type );


Then add the following code in the "b1_click" method to call the method "msgbox ":
Msgbox (0, "this is to use dllimpThe prompt box pops up when ORT calls DLL! "," Mug ", 0x30 );

6. Press F5 to run the program and click B1. The following prompt box is displayed:

(2) Dynamic Loading and calling of unmanaged functions in DLL

The above explains how to use dllimpORT calls the unmanaged function in DLL, but this is a global function. If the unmanaged function in dll has a static variable S, every time this function is called, the static variable s automatically adds 1. Results: When a new count is required, the expected results cannot be obtained. The following is an example:

1. Create DLL

1) Start visual c ++ 6.0;

2) create a "Win32 dynamic-Link Library" project named "count ";

3) on the "DLL kind" selection page, select "A simple DLL project ";

4) Open count. cpp and add the following code:
// Export the function, which is called using the _ stdcall standard.

Extern "C" _ declspec (dllexport) int _ stdcall count (INT init );

Int _ stdcall count (INT init)

{// Count function, uses the init parameter to initialize the static integer variable S, and returns this value after s Auto-increment 1.

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. Use dllimpORT calls the count function in DLL

1) Open the project "TZB" and add a button to the "form1" form.

2) Change the button attribute: name is "B2", text is "dllimp"ORT calls the count function in DLL, and adjusts the button B1 to the appropriate size to move it to the appropriate position.

3) Open the "form1.cs" Code view, use the static and extern keywords to declare the method "count", and enable it to implement 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 "b2_click" method:
MessageBox. Show ("use dllimpORT calls the count function in DLL. The input parameter n is 0. The result is: "+ count (0). tostring ()," Challenge Cup ");

MessageBox. Show ("use dllimpORT calls the count function in DLL. The input value of N is 10. The result is: "+ count (10 ). tostring () + "N is not the expected 11 !!! "," Challenge Cup ");

MessageBox. Show ("The result shows that N uses dllimpORT calls the unmanaged n function in DLL to be 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 "B2" to bring up the following three prompt boxes:

The 1st prompt boxes show the results of calling "count (0)", and the 2nd prompt boxes show the results of calling "count (10)". The results can prove that "use dllimpThe unmanaged functions in the ORT Call DLL are global and static functions ". Therefore, sometimes it cannot achieve our goal, so we need to use the method described below: C # dynamic call of functions in DLL.

3. C # dynamically call functions in DLL

Because dllimp is used in C #ORT cannot be like dynamic load/unload assembly, so you can only use API functions. In kernel32.dll, functions related to dynamic library calling include [3]:

① Loadlibrary (or afxloadlibrary of MFC) to load dynamic libraries.

② Getprocaddress: Get the function to be introduced and convert the symbol name or ID number to the internal DLL address.

③ Freelibrary (or afxfreelibrary of MFC) to release the dynamic link library.

Their prototypes are:

Hmodule loadlibrary (lpctstr lpfilename );

Farproc getprocaddress (hmodule, lpcwstr lpprocname );

Bool freelibrary (hmodule );

Now, we can use intptr hmodule = loadlibrary ("count. DLL); to obtain the DLL handle, use intptr farproc = getprocaddress (hmodule, "_ count @ 4"); to obtain the function entry address.

But how can I call this function after knowing the function entry address? Because there is no function pointer in C # and there is no function pointer call method like C ++ to call the function, we have to use other methods. After research, we found that we can achieve our goal by combining the classes and functions in system. reflection. emit and system. reflection. assembly. For future convenience and code reuse, we can write a class.

1) write the DLD class:

1. open the project "TZB", open the Class View, right-click "TZB", select "add" --> "class", and set the class name to "DLD ", that is, the start letter of each word in dynamic loading DLL.

2. Add the required namespace and declare the parameter transfer method enumeration:
Using system. runtime. interopservices; // use dllimpThis namespace is required for ORT

Using system. reflection; // This namespace is required for using the Assembly class

Using system. reflection. emit; // This namespace is required to use ilgenerator

Add the following code to the public class DLD to declare the parameter transfer method enumeration:
/// <Summary>

/// Parameter transfer mode enumeration, byvalue indicates value transfer, byref indicates Address Transfer

/// </Summary>

Public Enum modepass

{

Byvalue = 0x0001,

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> handle of the function library module </returns>

[DllimpORT ("kernel32.dll")]

Static extern intptr loadlibrary (string lpfilename );

/// <Summary>

/// The prototype is farproc getprocaddress (hmodule, lpcwstr lpprocname );

/// </Summary>

/// <Param name = "hmodule"> handle of the function library module to be called </param>

/// <Param name = "lpprocname"> name of the called function </param>

/// <Returns> function pointer </returns>

[DllimpORT ("kernel32.dll")]

Static extern intptr getprocaddress (intptr hmodule, string lpprocname );

/// <Summary>

/// Prototype: bool freelibrary (hmodule );

/// </Summary>

/// <Param name = "hmodule"> handle of the function library module to be released </param>

/// <Returns> whether the specified dll has been released </returns>

[DllimpORT ("Kernel32", entrypoint = "freelibrary", setlasterror = true)]

Static extern bool freelibrary (intptr hmodule );

/// <Summary>

/// Handle of the 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. added the loaddll method and reloaded this method for convenience during the call:

/// <Summary>

/// Load the DLL

/// </Summary>

/// <Param name = "lpfilename"> DLL file name </param>

Public void loaddll (string lpfilename)

{

Hmodule = loadlibrary (lpfilename );

If (hmodule = intptr. Zero)

Throw (new exception ("not found:" + lpfilename + "."));

}

If you already have a DLL handle, you can use the second version of the loaddll method:
Public void loaddll (intptr hmodule)

{

If (hmodule = intptr. Zero)

Throw (new exception ("the handle hmodule of the passed function library module is empty ."));

Hmodule = hmodule;

}

5. Add the loadfun method and reload this method for the convenience of calling. The code and comments of the method are as follows:
/// <Summary>

/// Obtain the function pointer

//

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.