Recent use of DllImport, from the internet after Google found that most of the content is the same, and from the MSDN collection, the content is now summarized, to share with you.
When you're actually working on C # , you might ask: Why do we want to rewrite code for something that already exists (such as some of the features in Windows thathave been written in C + +)?C # is there a way to use these existing functions directly? The answer is yes, you can call these features directly from the DllImport in C #.
DllImport is an attribute class under the System.Runtime.InteropServices namespace, so ASP. NET to use dllimport, you must first "using System.Runtime.InteropServices;". Its function is to provide the information necessary to make a call from a function exported from an unmanaged DLL. The DllImport property is applied to a method, requiring a minimum of the name of the DLL that contains the entry point.
DllImport Property Definition
As follows:
Namespace System.Runtime.InteropServices
{
[AttributeUsage (AttributeTargets.Method)]
public class DllImportAttribute:System.Attribute
{
Public DllImportAttribute (String dllName) {...} Positioning parameter is Dllname
Public callingconvention callingconvention; Entry point calling convention
Public CharSet CharSet; The entry point uses a character connection
public string entrypoint; Entry point Name
public bool exactspelling; Whether the spelling must be exactly the same as the entry point indicated, false by default
public bool PreserveSig; Whether the signature of the method is preserved or converted
public bool SetLastError; The return value of the Findlasterror method is saved here
public string Value {get {...}}
}
}
Description
1, DllImport can only be placed on the method declaration.
2. DllImport has a single positional parameter: Specifies the DllName parameter that contains the DLL name of the imported method.
3. DllImport has five named parameters:
A, the CallingConvention parameter indicates the calling convention of the entry point. If CallingConvention is not specified, the default value of Callingconvention.winapi is used.
b, the charset parameter specifies the character set used at the entry point. If CharSet is not specified, the default value of CharSet.Auto is used.
The C, entrypoint parameter gives the name of the entry point in the DLL. If entrypoint is not specified, the name of the method itself is used.
The D, exactspelling parameter indicates whether the entrypoint must exactly match the spelling of the indicated entry point. If ExactSpelling is not specified, the default value of false is used.
E, the PreserveSig parameter indicates whether the signature of the method is preserved or converted. When the signature is converted, it is converted to a signature of an additional output parameter named RetVal with the HRESULT return value and the return value. If PreserveSig is not specified, the default value of True is used.
The F, setlasterror parameter indicates whether the method retains Win32 "previous error". If SetLastError is not specified, the default value of false is used.
4, it is a one-time attribute class.
5. The method modified with the DllImport property must have an extern modifier.
DllImport Usage Example (a win32api to write to the INI file):
DllImport ("kernel32")
private static extern long WritePrivateProfileString (string section,string key,string val,string filePath);
The data type corresponding to the invocation of WINAPI with this method: Dword=int or Uint,bool=bool, predefined constants =enum, Structure =struct.
DllImport path PROBLEM:
3. Environment variable Directory
So you just need to copy the referenced DLL into these three directories so you don't have to write the path.
In the web, but also in the application
It was later found that using [DllImport (@ "C:\OJ\Bin\Judge.dll")] to specify the absolute path of the DLL can be loaded normally.
This problem most often occurs when using third-party unmanaged DLL components, and mine is also the problem , the official solution for ASP. NET team is as follows :
First you need to make sure which components you refer to , which are managed , and which are unmanaged . Managed well , directly used by the need to reference , indirect use of the need to copy to the Bin directory . Unmanaged processing can be tricky. In fact , you don't have any help copying to the bin because the CLR copies the files to a temporary directory and then runs the web, and the CLR only copies the managed files . This is why we clearly put the unmanaged DLL under the bin but still hint that the module cannot be loaded.
The following are the specific practices :
First of all we on the server to find a place to create a new directory , if for C:\DLL;
Then , in the environment variable , add this directory to the path variable;
Finally , copy all the unmanaged files to C:\DLL, or simply put the DLLs in the system32 directory.
This is not a workaround for applications that can be deployed on their own, but if we are using virtual space, we cannot register the path variable or copy our own DLL to the system32 directory. At the same time we do not necessarily know the physical path of our DLL.
DllImport can only use string constants, not Server.MapPath (@ "~/bin/judge.dll") to determine the physical path.
DllImport Slow loading problem:
However, I found that the call to this "unmanaged Dll" is quite slow, probably because my method requires remote authentication, but it is too slow. After a study, we finally thought of a perfect solution.
First we use
[DllImport ("kernel32.dll")]
private extern static IntPtr LoadLibrary (String path);
[DllImport ("kernel32.dll")]
private extern static IntPtr GetProcAddress (IntPtr lib, String FuncName);
[DllImport ("kernel32.dll")]
private extern static bool FreeLibrary (IntPtr Lib);
The addresses of the LoadLibrary and GetProcAddress functions are obtained, and the functions within our DLLs are obtained by using these two functions .
We can use Server.MapPath (@ "~/bin/judge.dll") to get the physical path of our DLL, then load it with LoadLibrary and finally use GetProcAddress Gets the function address to use.
The following code for the custom class completes the LoadLibrary mount and function call:
public class Dllinvoke
{
[DllImport ("kernel32.dll")]
private extern static IntPtr LoadLibrary (String path);
[DllImport ("kernel32.dll")]
private extern static IntPtr GetProcAddress (IntPtr lib, String FuncName);
[DllImport ("kernel32.dll")]
private extern static bool FreeLibrary (IntPtr Lib);
Private INTPTR hlib;
Public Dllinvoke (String dllpath)
{
Hlib = LoadLibrary (DllPath);
}
~dllinvoke ()
{
FreeLibrary (hlib);
}
Convert the function you want to execute to a delegate
Public Delegate Invoke (String apiname,type t)
{
INTPTR API = GetProcAddress (hlib, apiname);
Return (Delegate) marshal.getdelegateforfunctionpointer (api,t);
}
}
Called by the following code
public delegate int Compile (String command, StringBuilder inf);//Compile
Dllinvoke dll = new Dllinvoke (Server.MapPath (@ "~/bin/judge.dll"));
Compile Compile = (Compile) DLL. Invoke ("Compile", typeof (Compile));
StringBuilder inf;
Compile (@ "gcc a.c-o a.exe", INF); This is the compile function defined in the call to my DLL.
DllImport Usage Example:
a common type of WIN32 class library is used in C # programming :
1, a DWORD is a 4-byte integer, so we can use an int or uint as the C # corresponding type.
2, bool type and bool corresponding.
Example One : Call the Beep () API to make a sound
Beep () is defined in Kernel32.lib, defined in MSDN, Beep has the following prototypes:
BOOL Beep (DWORD dwfreq,//Sound frequency
DWORD dwduration//sound duration);
Write the following prototypes in C #:
[DllImport ("kernel32.dll")]
public static extern bool Beep (int frequency, int duration);
Example Two : enumeration types and Constants
MessageBeep () is defined in User32.lib, defined in MSDN, MessageBeep has the following prototypes:
BOOL MessageBeep (UINT utype//sound type
);
Write the prototype in C #:
public enum Beeptype
{
Simplebeep =-1,
Iconasterisk = 0x00000040,
Iconexclamation = 0x00000030,
Iconhand = 0x00000010,
Iconquestion = 0x00000020,
Ok = 0x00000000,
}
The Utype parameter actually accepts a set of predefined constants, and it is reasonable to use the enum type for the Utype parameter.
[DllImport ("User32.dll")]
public static extern boolmessagebeep (Beeptype beeptype);
example three : processing structure
Sometimes I need to determine the battery condition of my laptop. WIN32 provides power management functions for this purpose, and searching MSDN can find the getsystempowerstatus () function.
BOOL getsystempowerstatus (Lpsystem_power_status lpsystempowerstatus);
This function contains a pointer to a struct that we have not processed. To work with structs, we need to define the structure in C #. We start with an unmanaged definition:
typedef struct _SYSTEM_POWER_STATUS {
BYTE aclinestatus;
BYTE Batteryflag;
BYTE batterylifepercent;
BYTE Reserved1;
DWORD batterylifetime;
DWORD batteryfulllifetime;
} system_power_status, *lpsystem_power_status;
Then, you get the C # version by replacing C type with a C # type .
struct SystemPowerStatus
{
BYTE ACLineStatus;
BYTE Batteryflag;
BYTE BatteryLifePercent;
BYTE reserved1;
int batterylifetime;
int batteryfulllifetime;
}
This makes it easy to write a C # prototype:
[DllImport ("kernel32.dll")]
public static extern bool GetSystemPowerStatus (ref SystemPowerStatus SystemPowerStatus);
In this prototype, we use "ref" to indicate that the struct pointer will be passed instead of the structure value. This is the general method of handling the structure passed through the pointer.
This function works fine, but it's a good idea to define the ACLineStatus and batteryflag fields as enums:
Enum Aclinestatus:byte
{
Offline = 0,
Online = 1,
Unknown = 255,
}
Enum Batteryflag:byte
{
High = 1,
Low = 2,
Critical = 4,
Charging = 8,
Nosystembattery = 128,
Unknown = 255,
}
Note that because the structure field is some bytes, we use byte as the base type of the enum.
Calling C + + code in two C #
int type
public static extern int MySum (int a1,int B1); Returns an int type
extern "C" __declspec (dllexport) int WINAPI mySum (int a2,int b2) //dll Declaration
{
A2 B2 can't change A1 B1
A2=.
B2= ...
return a+b;
}
{
Can change A1, B1
*a2= ...
*b2= ...
}
DLL to be passed into char * type
[DllImport ("MyDLL.dll")]
Incoming value
public static extern int MySum (string astr1,string bstr1);
DLL in the Declaration
extern "C" __declspec (dllexport) int WINAPI mySum (char * Astr2,char *bstr2)
{
Change Astr2bstr 2, astr1 bstr1 will not be changed
return a+b;
}
Outgoing value
Outgoing char * Change Astr BSTR-->abuf, BBUF can be changed
BOOL EnumWindows (Wndenumproc lpenumfunc, LPARAM LPARAM)
Usingsystem; Using System.Runtime.InteropServices; Public delegate bool CallBack (int hwnd, int lParam); Defines the delegate function type public class Enumreportapp { [DllImport (' User32 ')] public static extern int EnumWindows (CallBack x, int y); public static void Main ()
{ CallBack mycallback = new CallBack (enumreportapp.report);
EnumWindows (mycallback, 0); } public static BOOL Report (int hwnd, int. LParam) { console.write ("Window handle is"); Console.WriteLine (HWND); return true; } }
DLL Transfer Structure BOOL ptinrect (const RECT *LPRC, point pt); Using System.Runtime.InteropServices; [StructLayout (layoutkind.sequential)] public struct point
{public int x, public int y; } [StructLayout (layoutkind.explicit)] public struct Rect {[FieldOffset (0)] public int left; [FieldOffset (4)] public int top; [FieldOffset (8)] public int right; [FieldOffset] public int bottom; } Class XXXX
{[DllImport ("User32.dll")] public static extern bool PtInRect (ref Rect R, point P); }
For more information on the following four fields of DllImportAttribute see: C#dllimportattribute Usage Summary
DllImport Usage Summary in C #