zoukankan      html  css  js  c++  java
  • 使用平台调用(P/Invoke)

    使用平台调用

    P/Invoke。它的全名叫平台调用(platform invoke)。用于调用dll 中实现的非托管的单调(flat)编程接口。被称为使用C或C++ 调用约定(calling conventions)。最有名的样例是Win32 编程接口,这是一个巨大的库,它公开了Windows 全部的内置功能。

    为了调用单调的非托管编程接口,必须首先定义准备调用的函数。可以分成两步:第一步。用System.Runtime.InteropServices 命名空间下的 DllImport 特性(attribute),可以定义包括想导入函数的 .dll,加上一些其它的可选特性;第二步,用keywordextern。加以 C 风格函数调用的签名,这样。指定了返回类型为F# 类型,和函数的名字,最后是用括号括起来的參数类型和參数名。结果这个函数就能像外部的.NET 方法一样进行调用。

    以下的样例演示了怎样导入Windows 函数MessageBeep,并调用:

     

    open System.Runtime.InteropServices

    // declare a function found in an external dll
    [<DllImport("User32.dll")>]
    extern boolMessageBeep(uint32 beepType)

    // call this method ignoring the result
    MessageBeep(0ul) |> ignore

     

    注意

    使用平台调用,最棘手的问题就是要找出要调用函数的签名。在http://pinvoke.net 站点上有 C# 和 VB .NET 中经常使用编程接口的签名的清单。F# 中须要的签名也相类似。这个站点是一个维基百科(wiki),因此能够自由加入 F# 签名。

    以下的代码演示了怎样使用平台调用。目标函数期望一个指针,有关设置指针须要注意几点。当定义函数时,须要在类型名字的后面加星号(*)。表示传递指针;在函数调用之前。还要定义一个可变标识符,表示指针指向的内存区域,它可能不是全局的,可是在顶层,必须是函数定义的一部分。

    这就是为什么定义函数main,标识符status 是函数定义的一部分;最后,必须使用地址运算符(&&),保证传递给函数的是指针而不是值本身。

    提示

    编译这段代码总是有警告,由于使用了地址运算符(&&)。要抑制这个警告。能够使用编译器开关--nowarn 51,或者命令#nowarn 51。

    openSystem.Runtime.InteropServices

     

    // declare a function found in an external dll

    [<DllImport("Advapi32.dll")>]

    extern boolFileEncryptionStatus(string filename, uint32* status)

     

    let main() =

        //declare a mutable idenifier to be passed to the function

        let mutable status = 0ul

        // call thefunction, using the address of operator with the

        // secondparameter

        FileEncryptionStatus(@"C: est.txt", && status) |>ignore

        printfn"%d" status

     

    main()

     

    这个样例的执行结果例如以下(如果在 C: 盘根文件夹下有一个文件test.txt,加过密的):

     

    1ul

     

    注意

    平台调用也能够执行在 Mono 平台上,语法与 F# 中的全然一样。而难点在于保证要调用的库在全部的目标平台上都可用,且遵循在全部不同的平台上库的不同的命名约定。很多其它有关解释的细节,请看http://www.mono-project.com/Interop_with_Native_Libraries上的文章。

    DllImport 特性有一些实用的函数。可以设置用来控制怎样调用非托管的函数。表 14-1 做了汇总。

    表 14-1 DllImport 上实用的特性

     

    特性名

    描写叙述

    CharSet

    定义了传送字符串数据的字符集,能够是 CharSet.Auto、CharSet.Ansi、CharSet.Unicode

    EntryPoint

    设置调用函数的名字。

    假设没有给定名字,那么。keyword extern 后面的名字就作为默认定义的函数名。

    SetLastError

    这是一个逻辑值。指定是否遇到不论什么错误都应该传送,因此,通过调用 Marshell.GetLastWin32Error() 方法检查可用性。

     

    注意

    由于有 COM 组件。没有等价的.NET 的非托管编程接口的数量在持续降低,因此。在准备调用函数前检查一下是否有等价的托管函数。一般会节省大量时间。

  • 相关阅读:
    RANSAC算法——RANDOM SAMPLE CONSENSUS
    屏蔽关键词搜索
    全景图拼接——opencv之stitching
    如何 查看本地安装的 .NET Framework(CLR) 版本 方法二亲测可行
    js判断是否是ie浏览器且给出ie版本
    js判断文件大小利用img 的 dynsrc,兼容IE10 及以上
    Java的——String类、StringBuffer和StringBuilder、不可变和可变字符序列使用陷阱
    windows.onload和body的onload属性的区别
    jquery中class选择器的用法,选择两个class
    #JS# 如何判断一个字符串是否为日期格式
  • 原文地址:https://www.cnblogs.com/liguangsunls/p/6708948.html
Copyright © 2011-2022 走看看