Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/fsharp/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Winapi F#使用Marshallas的P/Invoke签名的语法_Winapi_F#_Pinvoke_Marshalling - Fatal编程技术网

Winapi F#使用Marshallas的P/Invoke签名的语法

Winapi F#使用Marshallas的P/Invoke签名的语法,winapi,f#,pinvoke,marshalling,Winapi,F#,Pinvoke,Marshalling,我不确定这个的语法。我想把这个C代码翻译成F代码 这就是我目前所拥有的 type LASTINPUTINFO = { cbSize : UInt32; dwTime : UInt32; } type IdleTimer = [<DllImport("User32.dll")>] [<return: MarshalAs(UnmanagedType.Bool)>] extern GetLastInputInfo(plii : LAST

我不确定这个的语法。我想把这个C代码翻译成F代码

这就是我目前所拥有的

type LASTINPUTINFO = {
    cbSize : UInt32;
    dwTime : UInt32;
}

type IdleTimer =
    [<DllImport("User32.dll")>]
    [<return: MarshalAs(UnmanagedType.Bool)>]
    extern GetLastInputInfo(plii : LASTINPUTINFO ref)
type LASTINPUTINFO={
cbSize:UInt32;
dwTime:UInt32;
}
型惰轮=
[]
[]
外部GetLastInputInfo(plii:LASTINPUTINFO参考)

老实说,我还没有试着运行或使用它,但它可以编译,希望能引导您朝着正确的方向前进

open System
open System.Runtime.InteropServices 

[<Struct>]
type LASTINPUTINFO = 
    val cbSize : UInt32
    val dwTime : UInt32

module IdleTimer =
    [<DllImport("User32.dll")>]
    extern [<MarshalAs(UnmanagedType.Bool)>] bool GetLastInputInfo([<In>][<Out>] LASTINPUTINFO plii)
开放系统
open System.Runtime.InteropServices
[]
类型LASTINPUTINFO=
val cbSize:UInt32
val dwTime:UInt32
模块空闲器=
[]
extern[]布尔GetLastInputInfo([]LASTINPUTINFO plii)

除了Brian的评论之外,可能值得指出的是,F#外部签名相当忠实地反映了C签名,因此,您可能只需将参数声明为
LASTINPUTINFO*plii
,而不必在引用中使用
[][]
属性,然后在调用函数时使用&&运算符传递对本地实例的引用。

除了kvb的注释外,我发现将参数声明为指针会使当前的FSharp Power Tools重构引擎出错。您可以使用
IntPtr
绕过以下问题:

open System
open System.Runtime.InteropServices 
open Microsoft.FSharp.NativeInterop

[<Struct>]
type LASTINPUTINFO = 
  val mutable cbSize : uint32
  val dwTime : uint32

[<DllImport("user32.dll")>]
extern bool GetLastInputInfo(IntPtr p)

let getLastInputTime() = 
  let mutable time = LASTINPUTINFO(cbSize = 8u)
  GetLastInputInfo(NativePtr.toNativeInt &&time) |> ignore
  time.dwTime
开放系统
open System.Runtime.InteropServices
打开Microsoft.FSharp.NativeInterop
[]
类型LASTINPUTINFO=
val可变cbSize:uint32
val dwTime:uint32
[]
外部布尔GetLastInputInfo(IntPtr p)
让getLastInputTime()=
设可变时间=LASTINPUTINFO(cbSize=8u)
GetLastInputInfo(NativePtr.toNativeInt&&time)|>忽略
时间
最新答案:

在大多数情况下,当使用p/Invoke时,可以简单地从C头文件(当然是无分号)复制并粘贴签名。然而,至少有一种情况是,天真地这样做会产生不可验证类型安全的代码。让我们看一个具体的例子。给定C中的以下函数原型:

__declspec(dllexport) void getVersion (int* major, int* minor, int* patch);
可以在F#中使用以下p/Invoke签名(和相关调用):

[]
外部无效获取版本(int*主、int*次、int*补丁)
设可变主、次、面片=0,0,0
getVersion(&&major,&&minor,&&patch)
printfn“版本:%i.%i.%i”主-次修补程序
然而,这并不完全正确。事实证明,在处理CLR时,有两种类型的指针:非托管指针和托管指针。后者是通过引用传递CLR类型时使用的(即F#中的“byref”,C#中的“ref”,或VB中的“byref”)。如果您希望F#代码是可验证的类型安全的,那么您也应该使用托管变体,这包括P/Invoke调用。如果您考虑一下,这是有意义的。运行时只能保证它可以控制的位(即“托管”的部分).下面是F#代码使用托管指针的样子:

[<DllImport("somelib",CallingConvention=CallingConvention.Cdecl)>]
extern void getVersion (int& major, int& minor, int& patch)

let mutable major,minor,patch = 0,0,0
getVersion(&major,&minor,&patch)
printfn "Version: %i.%i.%i" major minor patch
[]
外部无效获取版本(内部和主要版本、内部和次要版本、内部和修补版本)
设可变主、次、面片=0,0,0
getVersion(主版本、次版本和修补程序)
printfn“版本:%i.%i.%i”主-次修补程序
便利桌:

Pointer    F#             Type Declaration      Invocation
Unmanaged  nativeint      <type>*               &&<type>
Managed    byref <type>   <type>&               &type
指针F#类型声明调用
非托管本地*&&
托管byref&类型
在几乎所有情况下,.NET开发人员都应该更喜欢托管指针。将非托管风险留给C代码

编辑来源:

另外,要作为byref传入,必须将变量标记为可变。传递不可变对象(即使具有可变属性)是只读inref。便于通过引用传递只读值类型

[<DllImport("somelib",CallingConvention=CallingConvention.Cdecl)>]
extern void getVersion (int& major, int& minor, int& patch)

let mutable major,minor,patch = 0,0,0
getVersion(&major,&minor,&patch)
printfn "Version: %i.%i.%i" major minor patch
Pointer    F#             Type Declaration      Invocation
Unmanaged  nativeint      <type>*               &&<type>
Managed    byref <type>   <type>&               &type