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

来源:互联网 发布:淘宝客服售后话术大全 编辑:程序博客网 时间:2024/05/18 01:35
平台调用技术(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以多字节字符串的形式封送字符串。 由 .NET Compact Framework 支持Auto针对目标操作系统适当地自动封送字符串。在 Windows NT、Windows 2000、Windows XP 和 Windows Server 2003 系列上默认值为 Unicode;在 Windows 98 和 Windows Me 上默认值为 Ansi。尽管公共语言运行库默认值为 Auto,使用语言可重写此默认值。例如,默认情况下,C# 将所有方法和类型都标记为 Ansi。  None此值已过时,它与 CharSet.Ansi 具有相同的行为。 由 .NET Compact Framework 支持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 导出的类调用方法。 由 .NET Compact Framework 支持Winapi此成员实际上不是调用约定,而是使用了默认平台调用约定。例如,在 Windows 上默认为 StdCall,在 Windows CE.NET 上默认为 Cdecl。 

3、注意事项:

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

 

原创粉丝点击