【问题标题】:F# Passing Nulls to Unmanaged Imported DLLF# 将空值传递给非托管导入的 DLL
【发布时间】:2016-12-23 00:26:13
【问题描述】:

在 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 中使用的预定义类型。

有什么办法可以做到吗?

【问题讨论】:

  • 对于那些需要为null 的指针,使用nativeptr 而不是int&amp;,然后使用NativePtr.read/NativePtr.write 来获取/设置值。
  • @Fyodor 你能举个例子吗? extern int SDL_QueryTexture(nativeint texture, uint32&amp; format, nativeptr&lt;int&gt; access, int&amp; w, int&amp; h) 无法编译。
  • 发布了答案。抱歉耽搁了很长时间,有点忙。

标签: f# dllimport


【解决方案1】:

如果要指定空值,则需要使用“原始指针”,由nativeint 和nativeptr&lt;T&gt; 类型表示。

[<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 )

【讨论】:

  • 不确定这是如何标记的答案 - nativeint 类型没有 'null' 作为正确值。从 2016 年到现在,FSharp 是否发生了变化?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-10-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-07-30
相关资源
最近更新 更多