使用平台调用

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:\test.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 的非托管编程接口的数量在持续降低,因此。在准备调用函数前检查一下是否有等价的托管函数。一般会节省大量时间。

使用平台调用(P/Invoke)的更多相关文章

  1. 在 C# 中通过 P/Invoke 调用Win32 DLL

    在 C# 中通过 P/Invoke 调用Win32 DLL 发布日期 : 1/13/2005 | 更新日期 : 1/13/2005 Jason Clark 下载本文的代码: NET0307.exe ( ...

  2. Net调用非托管代码(P/Invoke与C++InterOP) [转]

    将 System::String 转换为 wchar_t* 或 char* PtrToStringChars将String转换为本机wchar_t *或char *.由于 CLR 字符串为内部 Uni ...

  3. .NET Framework 框架的一些简单介绍

    20世纪90年代以来出现的3种典型的组件技术: 1)OMC(对象组件模型)的CORBA2)Microsoft的COM/DCOM3)Sun公司的JavaBeans 在2002年,微软发布了.NET框架的 ...

  4. cefglue埋坑记录

    很少写博客,写的不好,请多多包含,主要是记录工作中的一些问题,和园子里朋友一起讨论学习. 写埋坑记录之前,我先介绍下为什么会使用这个webkit内核的浏览器组件,我是wpf项目使用富文本编辑器,话说w ...

  5. Silverlight之OOB模式下的一些事

    本文简介: 1.为什么要使用OOB?使用OOB的作用? 2.如何实现OOB模式 3.对OOB进行一些设置: 4.检测OOB的安装状态: 5.更新应用程序: 6.WebBrowser控件: 7.桌面通知 ...

  6. 在C#中使用 Win32 和其他库

    C# 用户经常提出两个问题:“我为什么要另外编写代码来使用内置于 Windows® 中的功能?在框架中为什么没有相应的内容可以为我完成这一任务?”当框架小组构建他们的 .NET 部分时,他们评估了为使 ...

  7. C# API 大全

    C:\ProgramFiles\MicrosoftVisual Studio .NET\ FrameworkSDK\Samples\ Technologies\ Interop\PlatformInv ...

  8. .NET Framework基本概念

    http://blog.csdn.net/T573029173/article/details/41730101 .NET是微软的新一代技术平台.对技术人员来说,想真正了解什么是.NET,须先了解.N ...

  9. C#中一些默认的预定义属性

    C#中一些默认的预定义属性,见下表: 预定义的属性 有效目标 说明 AttributeUsage Class 指定另一个属性类的有效使用方式 CLSCompliant 全部 指出程序元素是否与CLS兼 ...

随机推荐

  1. pip安装注意事项

    pip源 清华:https://pypi.tuna.tsinghua.edu.cn/simple 阿里云:http://mirrors.aliyun.com/pypi/simple/ 中国科技大学 h ...

  2. 【LeetCode】52. N-Queens II

    N-Queens II Follow up for N-Queens problem. Now, instead outputting board configurations, return the ...

  3. xcode 在哪里新建category、protocol等文件

    1.和以前新建新文件一样.2.当然选IOS啦,不过OS X也有这个选项,然后Objctive-C File. 3.在File Type里选就OK啦.

  4. 图解最小生成树 - 普里姆(Prim)算法

    我们在图的定义中说过,带有权值的图就是网结构.一个连通图的生成树是一个极小的连通子图,它含有图中全部的顶点,但只有足以构成一棵树的n-1条边.所谓的最小成本,就是n个顶点,用n-1条边把一个连通图连接 ...

  5. C#方法参数--值参数,引用参数,输出参数

    值参数: 使用值参数,通过复制实参的值到形参的方式,把数据传递到方法,方法被调用的时候,系统做如下操作: 在栈中为形参分配空间: 复制实参到形参. 注意:一个值参数的实参不一定是变量,它可以是任何能够 ...

  6. 利用WGET下载文件,并保存到指定目录

    wget是Linux上一个非常不错的下载指令,也算是Linux工作者常用的指令之一 而这个指令我想在各大系统都预设有提供,包括了Ubuntu.Fedora等,而一般来说,要使用wget下载档案,只需要 ...

  7. SpringCloud 分布式配置

    转 http://www.cnblogs.com/zhangjianbin/p/6347247.html 前言 在单体式应用中,我们通常的做法是将配置文件和代码放在一起,这没有什么不妥.当你的应用变得 ...

  8. HTML5游戏实战之精灵翻转

    要实现精灵的翻转.很easy.先看实际效果点这里. 代码仅仅有区区几行: var sp = this.getWindow().find("ui-status2-general"); ...

  9. jQuery $.extend()使用方法

    $.extend()使用方法总结. jQuery为开发插件提拱了两个方法,各自是: jQuery.fn.extend(object); jQuery.extend(object); jQuery.ex ...

  10. 按“块”的方式写dom以及代码注释

    前言 首先这个文档中主要记述了自己在编写html代码时如何构建良好的dom结构的一些所思所想,在这一部分主要说明按“块”构建dom结构的思路.同时在这篇文档中也记述了自己对代码注释的理解,在这一部分主 ...