如何在C#中处理null或者可选的dll struct参数

Riv*_*ver 13 c# null pinvoke interop optional-parameters

如何struct使用pinvoke 处理从C#调用的dll方法中的可选参数?例如,lpSecurityAttributes此处参数应该null在不存在时传递.

正确的传递方式struct似乎正在使用ref,但它不能有可选参数,或者null总的来说.

有什么方法可以达到这个目的?

Riv*_*ver 16

你有几个选择

1)使用a class而不是astruct

我认为这种方法最简单.只需声明structclass:

[StructLayout(LayoutKind.Sequential)]
public class CStruct
{
    //member-list
}
Run Code Online (Sandbox Code Playgroud)

然后声明你的方法:

[DllImport("mydll.dll", OptionName = optionValue, ...)]
static extern int DLLFunction(CStruct cStruct, ...);
Run Code Online (Sandbox Code Playgroud)

如果您的可选参数恰好是最后一个参数,则可以将其CStruct cStruct = null用作参数.这允许您排除它而不是null显式传递.您还可以编写一个使用此方法的包装器方法,并确保可选参数最后.

2)使用IntPtrIntPtr.Zero

使用struct:

[StructLayout(LayoutKind.Sequential)]
public struct CStruct
{
    //member-list
}
Run Code Online (Sandbox Code Playgroud)

并将您的方法声明为:

[DllImport("mydll.dll", OptionName = optionValue, ...)]
static extern int DLLFunction(IntPtr cStruct, ...);
Run Code Online (Sandbox Code Playgroud)

在非null大小写中,将结构编组为指针并调用方法:

IntPtr ptr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(CStruct)));
try{
    Marshal.StructureToPtr(myCStruct, ptr, false);
    DLLFunction(ptr, ...);
} finally {
    Marshal.FreeHGlobal(ptr);
}
Run Code Online (Sandbox Code Playgroud)

在这种null情况下,调用方法IntPtr.Zero:

DLLFunction(IntPtr.Zero, ...);
Run Code Online (Sandbox Code Playgroud)

同样,如果这恰好是列表中的最后一个(或者使用包装器来实现),则可以使此参数成为可选参数.通过使用IntPtr cStruct = default(IntPtr)参数来完成此操作.(default(IntPtr) 创建一个IntPtr.Zero.)

3)重载您的方法以避免编组

使用struct2) .

只需为非null案例声明一个选项:

[DllImport("mydll.dll", OptionName = optionValue, ...)]
static extern int DLLFunction(ref cStruct, ...);
Run Code Online (Sandbox Code Playgroud)

另一个null案例:

[DllImport("mydll.dll", OptionName = optionValue, ...)]
static extern int DLLFunction(IntPtr cStruct, ...);
Run Code Online (Sandbox Code Playgroud)

传递a时会自动调用第一种方法,传递时会自动调用struct第二种方法IntPtr.Zero.如果IntPtr使用可选参数声明版本(如上面2所示),则在排除cStruct参数时它会自动调用它.

4)使用的原始指针 unsafe

使用2)中的结构并声明您的方法(注意unsafe关键字):

[DllImport("mydll.dll", OptionName = optionValue, ...)]
static unsafe extern int DLLFunction(CStruct* cStruct, ...);
Run Code Online (Sandbox Code Playgroud)

在非null案例中,您通过&myCStruct,简单地说就是null这种null情况.与1)中一样,如果此可选参数为last,则可以将参数声明为在排除时CStruct* cStruct = null自动传递.nullcStruct

感谢@dialer建议这种方法.