繁体   English   中英

如何处理 null 或可选的 DLL 结构参数

[英]How do I handle null or optional DLL struct parameters

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

传递struct的正确方法似乎是使用ref ,但它不能有可选参数,或者一般采用null

有什么方法可以实现这一目标?

你有几个选择

1) 使用class而不是struct

我认为这个方法是最简单的。 只需将struct声明为class

[StructLayout(LayoutKind.Sequential)]
public class CStruct
{
    //member-list
}

然后声明你的方法:

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

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

2) 使用IntPtrIntPtr.Zero

使用struct

[StructLayout(LayoutKind.Sequential)]
public struct CStruct
{
    //member-list
}

并将您的方法声明为:

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

在非null情况下,将结构编组为指针并调用该方法:

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

null情况下,使用IntPtr.Zero调用方法:

DLLFunction(IntPtr.Zero, ...);

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

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

使用2) 中struct

只需为非null情况声明一个选项:

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

另一个用于null情况:

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

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

4) 使用unsafe原始指针

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

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

在非null的情况下,你通过&myCStruct ,索性nullnull情况。 1) 一样,如果这个可选参数是最后一个,你可以将该参数声明为CStruct* cStruct = null以在排除cStruct时自动传递null

感谢@dialer 提出这种方法。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM