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