使用平台调用(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:\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)的更多相关文章
- 在 C# 中通过 P/Invoke 调用Win32 DLL
在 C# 中通过 P/Invoke 调用Win32 DLL 发布日期 : 1/13/2005 | 更新日期 : 1/13/2005 Jason Clark 下载本文的代码: NET0307.exe ( ...
- Net调用非托管代码(P/Invoke与C++InterOP) [转]
将 System::String 转换为 wchar_t* 或 char* PtrToStringChars将String转换为本机wchar_t *或char *.由于 CLR 字符串为内部 Uni ...
- .NET Framework 框架的一些简单介绍
20世纪90年代以来出现的3种典型的组件技术: 1)OMC(对象组件模型)的CORBA2)Microsoft的COM/DCOM3)Sun公司的JavaBeans 在2002年,微软发布了.NET框架的 ...
- cefglue埋坑记录
很少写博客,写的不好,请多多包含,主要是记录工作中的一些问题,和园子里朋友一起讨论学习. 写埋坑记录之前,我先介绍下为什么会使用这个webkit内核的浏览器组件,我是wpf项目使用富文本编辑器,话说w ...
- Silverlight之OOB模式下的一些事
本文简介: 1.为什么要使用OOB?使用OOB的作用? 2.如何实现OOB模式 3.对OOB进行一些设置: 4.检测OOB的安装状态: 5.更新应用程序: 6.WebBrowser控件: 7.桌面通知 ...
- 在C#中使用 Win32 和其他库
C# 用户经常提出两个问题:“我为什么要另外编写代码来使用内置于 Windows® 中的功能?在框架中为什么没有相应的内容可以为我完成这一任务?”当框架小组构建他们的 .NET 部分时,他们评估了为使 ...
- C# API 大全
C:\ProgramFiles\MicrosoftVisual Studio .NET\ FrameworkSDK\Samples\ Technologies\ Interop\PlatformInv ...
- .NET Framework基本概念
http://blog.csdn.net/T573029173/article/details/41730101 .NET是微软的新一代技术平台.对技术人员来说,想真正了解什么是.NET,须先了解.N ...
- C#中一些默认的预定义属性
C#中一些默认的预定义属性,见下表: 预定义的属性 有效目标 说明 AttributeUsage Class 指定另一个属性类的有效使用方式 CLSCompliant 全部 指出程序元素是否与CLS兼 ...
随机推荐
- Python接通图灵机器人
图灵机器人 图灵机器人特别low,问答水平并不高. import requests print("你好,我是图灵机器人") while 1: s = input() resp = ...
- Python的 numpy中 meshgrid 和 mgrid 的区别和使用
一.meshgrid函数 meshgrid函数通常使用在数据的矢量化上. 它适用于生成网格型数据,可以接受两个一维数组生成两个二维矩阵,对应两个数组中所有的(x,y)对. 示例展示: 由上面的示例展示 ...
- Web前端开发必备工具推荐
http://gaohaixian.blog.163.com/blog/static/12326010520114265223489/不管你做前端开发还是网页重构,前端工具都起着非常重要的作用,这里向 ...
- Java程序作linux服务并且开机自动启动[转]
以有个java应用名称为test,打包为test.jar,程序入口为cn.com.ppnote.SocketServer. 下面在linux的/opt下建立testapp目录,复制test.jar到/ ...
- 使用Visual Studio code
快捷键 ctrl+b 打开或关闭侧边栏 ctrl+\ 打开多个editor ctrl+e 快速的通过名字打开一个文件 右键选择 Reveal in Explorer 打开文件夹 ctrl+tab 快速 ...
- POSIX 消息队列 和 系列函数
一.在前面介绍了system v 消息队列的相关知识,现在来稍微看看posix 消息队列. posix消息队列的一个可能实现如下图: 其实消息队列就是一个可以让进程间交换数据的场所,而两个标准的消息队 ...
- Googleplay从服务器检索信息时出错。[DF-DFERH-01]
googleapis.cn services.googleapis.cn 两个地址强制走代理就OK了.
- cocos2dx当节点存在缩放时要注意的问题
cocos2dx(所有引擎也均如此),如果一个节点存在缩放,一定不要忘了其局部空间里的单位长度也会发生变化.其子节点位移,局部空间转世界空间结果等都会受影响. 有时候我们想将父节点的缩放转移到子节点中 ...
- java Webservice(一)HttpClient使用(一)
1.拳头之Get/Post拳头是最基本的一重武器,也是最重要的,好比练武之人必须先扎稳马步. java 代码 HttpClient httpclient=new HttpClient();//创建一个 ...
- php批量删除数据库下指定前缀的表
如何用php批量删除数据库下所有前缀为prefix_的表. 例子,统一删除前缀为“prefix_”的表. <?php //设置数据库连接信息.数据库服务器地址,数据库用户名,数据密码 mysql ...