kkm*_*kkm 4 f# pointers unsafe inline byref
在C#中,我写道
unsafe void Main() {
float f = 3.14f;
int i = *(int*)&f;
}
Run Code Online (Sandbox Code Playgroud)
是否可以将此代码转换为F#?
我的理解是指针是由nativeptr<'a>
类型表示的,但我对于我的生活我找不到相当于地址引用&
和指针解引用的*
运算符.我怀疑 NativePtr.get
可能是后者,但它的实现逃脱了我,因为我不太了解IL.
我知道BitConverter
和Marshal
,但我正在寻找一种方法来实现位修改而不复制内存.
该NativePtr.get
和set
功能读取和偏移写.如果需要逐字节读取,则使用它.如果你需要在零偏移处读取,你可以使用它read
,write
相反,它们会稍微提高性能.
byref<_>
调用"原始"地址(而不是引用)的运算符&&
(参见定义).
但是还有一些技巧涉及,例如:你需要先标记变量mutable
才能获取其地址,你不能只存储一个nativeptr<_>
值,你需要将其转换为nativeint
,加上nativeptr<_>
值是强类型的,所以你需要通过nativeint
等方式在它们之间进行转换
以下代码段将相当于您的C#代码(逐步完成并使用完整类型注释以提高清晰度):
open FSharp.NativeInterop
let Main() =
let mutable x: float = 3.1415
let floatPtr: nativeint = NativePtr.toNativeInt<float> &&x
let intPtr: nativeptr<int> = floatPtr |> NativePtr.ofNativeInt<int>
let asInt: int = NativeInterop.NativePtr.read intPtr
asInt
Run Code Online (Sandbox Code Playgroud)
或者更紧凑的版本:
open FSharp.NativeInterop
let Main() =
let mutable x = 3.1415
&&x |> NativePtr.toNativeInt |> NativePtr.ofNativeInt |> NativePtr.read<int>
Run Code Online (Sandbox Code Playgroud)
或将其打包以供重复使用:
// val inline readAs : x:'a -> 'b when 'a : unmanaged and 'b : unmanaged
let inline readAs (x: 'a) : 'b =
let mutable x' = x
&&x' |> NativePtr.toNativeInt |> NativePtr.ofNativeInt |> NativePtr.read<'b>
let Main() =
let i = readAs 3.1415 : int
()
Run Code Online (Sandbox Code Playgroud)
说完以上所有内容后,我完全赞同John Palmer和GuyCoder:如果可能的话,请不要这样做.这看起来就像Knuth博士警告我们的那种过早优化.
归档时间: |
|
查看次数: |
2153 次 |
最近记录: |