[英]How do I handle null or optional DLL struct parameters
如何使用 pinvoke 处理从 C# 调用的 dll 方法中的可选struct
参数? 例如, 此处的lpSecurityAttributes
参数不存在时应传递null
。
传递struct
的正确方法似乎是使用ref
,但它不能有可选参数,或者一般采用null
。
有什么方法可以实现这一目标?
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
。 您还可以编写一个使用此方法的包装器方法,并确保可选参数放在最后。
IntPtr
和IntPtr.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
。)
使用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
参数时自动调用它。
unsafe
原始指针使用2) 中的结构并声明您的方法(注意unsafe
关键字):
[DllImport("mydll.dll", OptionName = optionValue, ...)]
static unsafe extern int DLLFunction(CStruct* cStruct, ...);
在非null
的情况下,你通过&myCStruct
,索性null
的null
情况。 和1) 一样,如果这个可选参数是最后一个,你可以将该参数声明为CStruct* cStruct = null
以在排除cStruct
时自动传递null
。
感谢@dialer 提出这种方法。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.