nativeintとnativeptr<'T>とvoidptr
F#でポインターを扱う際によく登場するnativeint
とnativeptr<'T>
とvoidptr
についてまとめます。
各型について
nativeint
nativeint
は実のところ整数型です。内部的にはSystem.IntPtr
構造体へのエイリアスになっていますが、それだけではありません。そもそも.NETにおいて整数型には四則演算を行う演算子が定義されておらず、各言語がそれぞれに実装を用意しているだけです。そのため、C#言語においてIntPtr
型は整数型と見なされておらず四則演算できません。しかしF#は違います。IntPtr
およびnativeint
を整数型として扱い、四則演算を提供しています。
Marshal.Copy
メソッドのように多くのクラスライブラリはIntPtr
を使います。
nativeptr<'T>
C#言語におけるポインター型です。型としてはあまり登場しませんが、それでも例えばString(char* value)
のように引数に現れています。
voidptr
nativeptr<Void>
を特別扱いしたポインター型です。ReadOnlySpan<'T>(Void*, Int32)
コンストラクターのように最近よく登場するようになった気がします。
相互変換
クラスライブラリを呼び出す際、要求されるポインター型に変換する必要があります。相互変換方法を把握しておく必要があります。
nativeint
から nativeptr<'T>
NativePtr.ofNativeInt
を使います。
nativeptr<'T>
から nativeint
NativePtr.toNativeInt
を使います。
voidptr
から nativeptr<'T>
NativePtr.ofVoidPtr
を使います。
nativeptr<'T>
から voidptr
NativePtr.toVoidPtr
を使います。
nativeint
から voidptr
直接は変換できません。一旦nativeptr<'T>
を経由させる必要があります。その際、'T
が決定できませんし、既定のobj
では困りますので、明示的にnativeptr<byte>
などを経由させる必要があります。
voidptr
から nativeint
直接は変換できません。一旦nativeptr<'T>
を経由させる必要があります。その際、'T
が決定できませんし、既定のobj
では困りますので、明示的にnativeptr<byte>
などを経由させる必要があります。
相互変換その2
少しでも楽できないか考えました。
nativeint
から voidptr
nativeint
のエイリアス元であるIntPtr
にはToPointer()
メソッドがあり、これが使えます。
voidptr
から nativeint
nativeint
のエイリアス元であるIntPtr
にはIntPtr(Void*)
コンストラクターがあり、これが使えます。
Discussion