F# - 如何将数组转换为 nativeptr<double>
F# - How to convert array into nativeptr<double>
我需要与一些低级 C/FORTAN 库互操作。该库要求我提供一个回调函数,它在 C# 中具有以下签名:
public static class Interop
{
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public unsafe delegate void F(
ref int neq,
ref double t,
double* y,
double* yDot);
}
变量 neq
包含数组 y
和 yDot
的长度。外部库将提供指向这些数组的第一个元素的指针。
我可以轻松创建 F# 互操作以供该库使用,例如:
let private f (neq : byref<int>, t : byref<double>, x : nativeptr<double>, dx : nativeptr<double>) : unit =
for i in 0 .. (neq - 1) do
NativePtr.set dx i (NativePtr.get x i)
let createInterop() = Interop.F(fun n t y dy -> f(&n, &t, y, dy))
有效,我可以看到正在调用该函数并执行某些操作。
现在,我想编写一个测试,以确保我创建的互操作正常工作。
let interopTest() =
let neq = 10
let t = 0.0
let (x : double[]) = Array.zeroCreate n
let (dx : double[]) = Array.zeroCreate n
let interop = createInterop()
// Call the interop. ! DOES NOT COMPILE !
do interop.Invoke(ref neq, ref t, x, dx)
// Verify the results.
无论尝试什么,对 interop.Invoke
的调用都无法编译。对于上面的代码,它在 x
和 dx
处失败并显示消息:
[FS0001] This expression was expected to have type
'nativeptr<float>'
but here has type
'double []'
我可以将 neq
和 t
声明为可变的,然后像这样调用互操作:interop.Invoke(&neq, &t, ...
。那没有区别。但是,使用例如&dx.[0]
产生相同的编译器错误。
我需要将指向数组 x
和 dx
的第一个元素的指针传递给互操作函数。不幸的是,搜索如何在 F# 中将数组转换为 nativeptr 没有产生任何有用的结果。
谢谢。
这就是“如何在 F# 中将数组转换为 nativeptr”的方法:
open Microsoft.FSharp.NativeInterop
let private f (neq : byref<int>, t : byref<double>, x : nativeptr<double>, dx : nativeptr<double>) : unit =
for i in 0 .. (neq - 1) do
NativePtr.set dx i (NativePtr.get x i)
let createInterop() = fun n t y dy -> f(&n, &t, y, dy))
let interopTest() =
let n = 10
let t = 0.0
let (x : double[]) = Array.zeroCreate n
let (dx : double[]) = Array.zeroCreate n
let tx = NativePtr.ofNativeInt<double> x
let tdx = NativePtr.ofNativeInt<double> dx
let interop = createInterop()
// Call the interop. Does compile but does not call your c# interop
// but does create the correct nativeptr(s)
interop n t tx tdx
// Verify the results.
更新:
显然这对 OP 不起作用,但 tx
和 tdx
都产生相同的正确类型,无论哪种方式,在 VS Code 中,至少对我而言。无论如何,这显示了另一种有趣的做同样事情的方法,也许其他人可能会发现一个有效而另一个无效?
let interopTest() =
let n = 10
let t = 0.0
let (x : double[]) = Array.zeroCreate n
let (dx : double[]) = Array.zeroCreate n
let tx = fixed &x.[0] // val tx: nativeptr<double>
let tdx = fixed &dx.[0] // val tdx: nativeptr<double>
let interop = createInterop()
// Call the interop.
do interop.Invoke(ref n, ref t, tx, tdx)
// Verify the results.
我需要与一些低级 C/FORTAN 库互操作。该库要求我提供一个回调函数,它在 C# 中具有以下签名:
public static class Interop
{
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public unsafe delegate void F(
ref int neq,
ref double t,
double* y,
double* yDot);
}
变量 neq
包含数组 y
和 yDot
的长度。外部库将提供指向这些数组的第一个元素的指针。
我可以轻松创建 F# 互操作以供该库使用,例如:
let private f (neq : byref<int>, t : byref<double>, x : nativeptr<double>, dx : nativeptr<double>) : unit =
for i in 0 .. (neq - 1) do
NativePtr.set dx i (NativePtr.get x i)
let createInterop() = Interop.F(fun n t y dy -> f(&n, &t, y, dy))
有效,我可以看到正在调用该函数并执行某些操作。
现在,我想编写一个测试,以确保我创建的互操作正常工作。
let interopTest() =
let neq = 10
let t = 0.0
let (x : double[]) = Array.zeroCreate n
let (dx : double[]) = Array.zeroCreate n
let interop = createInterop()
// Call the interop. ! DOES NOT COMPILE !
do interop.Invoke(ref neq, ref t, x, dx)
// Verify the results.
无论尝试什么,对 interop.Invoke
的调用都无法编译。对于上面的代码,它在 x
和 dx
处失败并显示消息:
[FS0001] This expression was expected to have type
'nativeptr<float>'
but here has type
'double []'
我可以将 neq
和 t
声明为可变的,然后像这样调用互操作:interop.Invoke(&neq, &t, ...
。那没有区别。但是,使用例如&dx.[0]
产生相同的编译器错误。
我需要将指向数组 x
和 dx
的第一个元素的指针传递给互操作函数。不幸的是,搜索如何在 F# 中将数组转换为 nativeptr 没有产生任何有用的结果。
谢谢。
这就是“如何在 F# 中将数组转换为 nativeptr”的方法:
open Microsoft.FSharp.NativeInterop
let private f (neq : byref<int>, t : byref<double>, x : nativeptr<double>, dx : nativeptr<double>) : unit =
for i in 0 .. (neq - 1) do
NativePtr.set dx i (NativePtr.get x i)
let createInterop() = fun n t y dy -> f(&n, &t, y, dy))
let interopTest() =
let n = 10
let t = 0.0
let (x : double[]) = Array.zeroCreate n
let (dx : double[]) = Array.zeroCreate n
let tx = NativePtr.ofNativeInt<double> x
let tdx = NativePtr.ofNativeInt<double> dx
let interop = createInterop()
// Call the interop. Does compile but does not call your c# interop
// but does create the correct nativeptr(s)
interop n t tx tdx
// Verify the results.
更新:
显然这对 OP 不起作用,但 tx
和 tdx
都产生相同的正确类型,无论哪种方式,在 VS Code 中,至少对我而言。无论如何,这显示了另一种有趣的做同样事情的方法,也许其他人可能会发现一个有效而另一个无效?
let interopTest() =
let n = 10
let t = 0.0
let (x : double[]) = Array.zeroCreate n
let (dx : double[]) = Array.zeroCreate n
let tx = fixed &x.[0] // val tx: nativeptr<double>
let tdx = fixed &dx.[0] // val tdx: nativeptr<double>
let interop = createInterop()
// Call the interop.
do interop.Invoke(ref n, ref t, tx, tdx)
// Verify the results.