f# - 在 F# 中通过引用编组结构
问题描述
我正在尝试从 C# 到 F#的编组类、结构和联合 MSDN 文章中重写编组 SysTime 示例。
我的实际代码现在如下所示:
module LibWrap =
open System.Runtime.InteropServices
[<StructLayout(LayoutKind.Sequential)>]
type public SystemTime =
struct
val mutable public year:uint16
val mutable public month:uint16
val mutable public weekday:uint16
val mutable public day:uint16
val mutable public hour:uint16
val mutable public minute:uint16
val mutable public second:uint16
val mutable public millisecond:uint16
end
[<DllImport("Kernel32.dll")>]
extern void GetSystemTime([<param:In>][<param: Out>]SystemTime st)
[<EntryPoint>]
let main argv =
printfn "F# SysTime Sample using Platform Invoke";
let st = new LibWrap.SystemTime (month = 1us, day = 2us, year = 34us)
try
LibWrap.GetSystemTime st
with
| ex -> printfn "Failed to GetSystemTime: %O" ex
printfn "The Date is: %d/%d/%d" st.month st.day st.year
0
它毫无例外地编译和运行,但输出与预期不符。SystemTime 结构中的值不会被覆盖。
输出:
F# SysTime Sample using Platform Invoke
The Date is: 1/2/34
如果我在 F# 交互式控制台中运行代码,我得到System.AccessViolationException
. 代码的 C# 版本在我的系统上运行良好。我尝试使用ref
/byref
关键字,但这没有帮助。
有什么想法有什么问题吗?任何好的信息来源如何正确使用 F# 中的 P/Invoke 和编组?我没有找到太多有用的东西。
解决方案
Win32 GetSystemTime函数将结构参数定义为指针。这意味着如果您只是更改外部函数的定义方式,您的原始代码应该可以工作:
[<DllImport("Kernel32.dll")>]
extern void GetSystemTime(SystemTime& st)
然后,您将调整您的 main 方法以使其st
可变并像指针一样传递它:
[<EntryPoint>]
let main argv =
printfn "F# SysTime Sample using Platform Invoke";
let mutable st = LibWrap.SystemTime (month = 1us, day = 2us, year = 34us)
try
LibWrap.GetSystemTime &st
with
| ex -> printfn "Failed to GetSystemTime: %O" ex
printfn "The Date is: %d/%d/%d" st.month st.day st.year
0
这打印:
F# SysTime Sample using Platform Invoke
The Date is: 7/6/2018
推荐阅读
- rust - 对我的可写类型使用 fmt::Write 或 io::Write 特征?
- javascript - 通过javascript旋转图像
- multidimensional-array - 如何在 c++ 程序中插入名称列表,就像我们在 int 数组中插入整数一样
- angular - 通过比较两个列表来获取值
- c# - 解释和调整卡尔曼滤波器速度预测
- python - 嵌套列出到字典 python
- python - Python 计数 JSON 键值
- matlab - Matlab / Parse二进制文件读入内存
- python - 在python中分割一个数组,每个字段的值超过一个
- ios - iOS 13:表情符号键盘大小错误?