在F#我正在使用外部DLL(在这种情况下是SDL图形库)我正在导入我需要的方法如下…
[<DllImport("SDL2.dll", CallingConvention = CallingConvention.Cdecl)>]
extern int SDL_QueryTexture(nativeint texture, uint32& format, int& access, int& w, int& h)
这工作正常,我可以使用以下方法成功调用该方法…
let result = SDLDefs.SDL_QueryTexture(textTexture, &format, &access, &w, &h)
问题是本机SDL方法接受许多指针参数的空值.这在某些场景中是必需的(其功能类似于重载方法).我找不到任何方法从F#传递空值来调用这些方法.
例如,这失败了“没有null作为正确的值”
let result = SDLDefs.SDL_QueryTexture(textTexture, &format, null, &w, &h)
我读到了属性[AllowNullLiteral],但似乎我只能将它应用于我定义的类型,而不是我导入的DLL中使用的预定义类型.
有什么方法可以做到这一点吗?
最佳答案 如果要指定空值,则需要使用“原始指针”,它由nativeint和nativeptr< T>类型表示.
[<DllImport("SDL2.dll", CallingConvention = CallingConvention.Cdecl)>]
extern int SDL_QueryTexture(nativeint texture, uint32& format, nativeint access, int& w, int& h)
// Call without null
let access = 42
let pAccess = NativePtr.stackalloc<int> 1
NativePtr.write pAccess access
SQL_QueryTexture( textTexture, &format, NativePtr.toNativeInt pAccess, &w, &h )
let returnedAccess = NativePtr.read pAccess
// Call with null
SQL_QueryTexture( textTexture, &format, null, &w, &h )
注意:小心stackalloc.在堆栈上分配内存非常方便,因为您不需要显式释放它,但是一旦退出当前函数,指向它的指针将变为无效.因此,如果您确定该函数不会存储指针并稍后尝试使用它,那么您只能将这些指针传递给外部函数.
如果你需要将指针传递给不会去任何地方的真实堆内存,你需要Marshal.AllocHGlobal.但别忘了发布! (要不然 :-)
let access = 42
let pAccess = Marshal.AllocHGlobal( sizeof<int> )
NativePtr.write (NativePtr.ofNativeInt pAccess) access
SQL_QueryTexture( textTexture, &format, pAccess, &w, &h )
Marshal.FreeHGlobal( pAccess )