[DllImport("user32.dll", EntryPoint = "MessageBox")]
public static extern int DebugWin(int hwnd, string content, string lpcaption, int wType);
讲解下参数的含义
EntryPoint 是指向Dll中的一个方法
当设定了EntryPoint的指向后 自己定义的方法名就不需要与dll中的方法名相同了,因为EntryPoint已经指定了。系统是以 EntryPoint指向的方法为准。
如果没有设定EntryPoint那么自己定义的方法名就必须跟dll中要调用的方法名一致才可以。
[DllImport("user32.dll", EntryPoint = "MessageBox")]
public static extern int MessageBox(int hwnd, string content, string lpcaption, int wType);
否则会报EntryPointNotFoundException的异常。
extern修饰符 加上这个修饰符是为了告诉编译器此函数是在外部实现的,同时函数必须是标记了static
dll的位置可以是相对和绝对路径 DllImport(D:\TEST.dll) DllImport(TEST1.dll)
调用约定:
CallingConvention 用于指定传递方法参数的调用约定,多数 windows平台默认值是 StdCall,而 Windows CE 默认值是Cdecl。
如果调用方与dll中使用了不同的调用约定就可能会出现无法正确调用到函数的情况。所以如果dll中指定了调用约定,使用时就要保持调用约定的一致性。
示例:
c++中的函数:
extern "C" __declspec(dllexport)int __cdecl Test (int a, int b)
c#调用:
[DllImport("myTest.dll", CallingConvention = CallingConvention.Cdecl)]static extern int Test(int a, int b);
因为c++函数中明确使用了Cdecl的调用约定 所以在c#调用时就需要明确相同的调用约定,以防止无法正确调用。
先看下c#源码
namespace System.Runtime.InteropServices
{[ComVisible(true)]public enum CallingConvention{Winapi = 1,Cdecl = 2,StdCall = 3,ThisCall = 4,FastCall = 5}
}
CallingConvention是个枚举我们来按照顺序讲下枚举值的含义
Winapi: 使用默认平台的调用约定,就是说使用这个值,他会根据当前不同的平台使用对应平台中的默认约定
Cdecl: 调用方负责清理堆栈
StdCall: 被调用方负责清理堆栈
ThisCall:用于调用从非托管dll导出的类中的方法
FastCall :C#不支持此值,也不支持此调用约定