C#:如何将null传递给期望ref的函数?

Nic*_*ick 33 c# parameters null pinvoke ref

我有以下功能:

public static extern uint FILES_GetMemoryMapping(
    [MarshalAs(UnmanagedType.LPStr)] string pPathFile,
    out ushort Size,
    [MarshalAs(UnmanagedType.LPStr)] string MapName,
    out ushort PacketSize,
    ref Mapping oMapping,
    out byte PagesPerSector);
Run Code Online (Sandbox Code Playgroud)

我想这样称呼:

FILES_GetMemoryMapping(MapFile, out size, MapName,
    out PacketSize, null, out PagePerSector);
Run Code Online (Sandbox Code Playgroud)

不幸的是,我无法传递null一个需要类型的字段ref Mapping而且没有投射我已经尝试修复此问题.

有什么建议?

Jar*_*Par 32

我假设Mapping是一个结构?如果是这样,您可以使用FILES_GetMemoryMapping()具有不同签名的两个版本的原型.对于要传递的第二个重载,请将null参数设置为an IntPtr并使用IntPtr.Zero

public static extern uint FILES_GetMemoryMapping(
    [MarshalAs(UnmanagedType.LPStr)] string pPathFile,
    out ushort Size,
    [MarshalAs(UnmanagedType.LPStr)] string MapName,
    out ushort PacketSize,
    IntPtr oMapping,
    out byte PagesPerSector);
Run Code Online (Sandbox Code Playgroud)

电话示例:

FILES_GetMemoryMapping(MapFile, out size, MapName,
   out PacketSize, IntPtr.Zero, out PagePerSector);
Run Code Online (Sandbox Code Playgroud)

如果Mapping实际上是一个类而不是一个结构,只需将值设置为null,然后再将其传递给它.

  • 如果你有一个带结构的8指针的函数,你有什么建议呢?它们中的任何一个都可以为null?我应该写256次重载吗?使用可空值类型将虚拟变量工作? (3认同)

And*_*are 31

您无法传递的原因null是因为refC#编译器对参数进行了特殊处理.任何ref参数都必须是可以传递给您正在调用的函数的引用.因为你想传递null编译器是拒绝允许这个,因为你没有提供函数期望的引用.

你唯一真正的选择是创建一个局部变量,将其设置为null,然后传入.编译器不允许你做更多的事情.


Eri*_*bal 10

一种方法是创建一个虚拟变量,将其赋值为null,然后传入.


jon*_*onp 5

虽然@JaredPar的答案无疑是正确的答案,但还有另一个答案:unsafe代码和指针:

unsafe {
    Mapping* nullMapping = null;
    FILES_GetMemoryMapping(
            MapFile,
            out size,
            MapName,
            out PacketSize,
            ref *nullMapping,    // wat?
            out PagePerSector);
}
Run Code Online (Sandbox Code Playgroud)

看起来它应该在运行时失败,但事实并非如此,因为 和ref相互*抵消,并且 的结果值ref *nullMapping是空指针,这就是FILES_GetMemoryMapping()该参数将接收的值。

这可能不是一个好主意,但它是可能的