我可以让它工作:
[<DllImport("user32.dll")>]
extern bool GetClientRect(nativeint, RECT*)
let getClientRect hwnd =
let mutable r = RECT()
if GetClientRect(hwnd, &&r) = false then
raise <| System.Exception("GetClientRect failed")
r但无论出于什么原因,这只会让r归零,没有抛出异常:
[<DllImport("user32.dll")>]
extern bool GetClientRect(nativeint, [<Out>] RECT rect)
let getClientRect hwnd =
let mutable r = RECT()
if GetClientRect(hwnd, r) = false then
raise <| System.Exception("GetClientRect failed")
r当然,使用指针的问题是我得到了警告warning FS0051: The use of native pointers may result in unverifiable .NET IL code,这是可以理解的。
我能错过什么呢?
编辑:尽管已经回答了,但对于记录,结构定义:
[<Struct>]
type RECT =
val left:int
val top:int
val right:int
val bottom:int发布于 2012-06-22 10:40:17
它没有很好的文档记录,但是在F# P/Invoke签名中使用&符号是通过引用传递值的正确(也是最好的)方式。它将编译为与C# ref参数相同的类型签名;将[<Out>]添加到该参数可获得与C# out参数相同的签名。
[<DllImport("user32.dll")>]
extern bool GetClientRect(nativeint hWnd, [<Out>] RECT& rect)
let getClientRect hwnd =
let mutable r : RECT = Unchecked.defaultOf<_>
if GetClientRect(hwnd, &r) = false then
raise <| System.Exception("GetClientRect failed")
r请注意,一旦您将P/Invoke签名更改为使用byref<RECT>而不是nativeptr<RECT>,还需要将您在r上使用的address-of运算符(&&)更改为单个“与”(&)。
因为您只能从GetClientRect中获取一个值,所以将可变结果值初始化为Unchecked.defaultOf<_>是一种很好的做法,这样就可以清楚地知道它将被GetClientRect覆盖。
编辑:如果将P/Invoke签名更改为使用byref (&)不起作用,您还可以尝试在返回类型上显式指定编组行为。GetClientRect的MSDN文档说它返回一个BOOL,这与.NET bool不完全相同(BOOL是一个4字节的整数值)。
如果你想尝试一下:
[<DllImport("user32.dll")>]
extern [<return: MarshalAs(UnmanagedType.Bool)>] bool GetClientRect(
nativeint hWnd, [<Out>] RECT& rect)https://stackoverflow.com/questions/11149250
复制相似问题