平台调用P-INVOKE(一)--(基础篇)

平台调用技术(P/Invoke): 主要用于处理在托管代码中调用C/C++库函数及Win32 API函数等非托管函数的情形

一、基本要素

一个简单例子:
C++声明:
extern "C" __declspec(dllexport) int Multiply(int factorA, int factorB);
实现:
int Multiply(int factorA, int factorB)
{
    return factorA * factorB;
}

托管代码(C#)调用此非托管声明:
class Invoker
    {
        //声明非托管函数
        [DllImport("Interop.dll",EntryPoint = " Multiply",CharSet = CharSet.Ansi)]
       static extern int Multiply(int factorA, int factorB);
 }
总结: (声明托管函数)
1.函数声明:
   extern修饰符和static修饰符
2.DllImport属性 (常用)
 
  指定动态库:指明平台要调用的dll名称,此项不可缺少。
  指定入口点:EntryPoint 字段按名称或序号指定 DLL 函数,可以使用与原dll中不同名称,不填此项,默认为跟原函数名称一致。
  指定字符集: CharSet 字段控制字符串封送处理并确定平台调用在 DLL 中查找函数名的方式。有窄版本 (ANSI) 和宽版本 (Unicode)。MSDN如下说明:
  成员名称 说明
  Ansi 以多字节字符串的形式封送字符串。 
Auto 针对目标操作系统适当地自动封送字符串。在 Windows NT、Windows 2000、Windows XP 和 Windows Server 2003 系列上默认值为 Unicode;在 Windows 98 和 Windows Me 上默认值为 Ansi。尽管公共语言运行库默认值为 Auto,使用语言可重写此默认值。例如,默认情况下,C# 将所有方法和类型都标记为 Ansi。 
  None 此值已过时,它与 CharSet.Ansi 具有相同的行为。 
Unicode 以 Unicode 2 字节字符形式封送字符串。 

  指定调用约定:CallingConvention字段指定调用在非托管代码中实现的方法所需的调用约定。动态链接库导出的一般有两种调用协议,__stdcall和_cdecl。__cdecl是C/C++和MFC程序默认使用的调用约定:采用__cdecl约定时,函数参数按照从右到左的顺序入栈,并且由调用函数者把参数弹出栈以清理堆栈。因此,实现可变参数的函数只能使用该调用约定。__stdcall调用约定用于调用Win32 API函数。采用__stdcal约定时,函数参数按照从右 到左的顺序入栈,被调用的函数在返回前清理传送参数的栈,函数参数个数固定。 MSDN如下说明:
  成员名称 说明
  Cdecl 调用方清理堆栈。这使您能够调用具有 varargs 的函数(如 Printf),使之可用于接受可变数目的参数的方法。 
  FastCall 不支持此调用约定。 
  StdCall 被调用方清理堆栈。这是使用平台 invoke 调用非托管函数的默认约定。 
  ThisCall 第一个参数是 this 指针,它存储在寄存器 ECX 中。其他参数被推送到堆栈上。此调用约定用于对从非托管 DLL 导出的类调用方法。 
Winapi 此成员实际上不是调用约定,而是使用了默认平台调用约定。例如,在 Windows 上默认为 StdCall,在 Windows CE.NET 上默认为 Cdecl。 

3、注意事项:

       数个数、顺序、类型必须保持“等价”一致,函数名称和参数名称可以不一致。

 


你可能感兴趣的:(NET互操作)