白轻易

博客园 首页 新随笔 联系 订阅 管理

[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#不支持此值,也不支持此调用约定





posted on 2019-03-13 14:00  白轻易  阅读(321)  评论(0编辑  收藏  举报