如何处理使用pinvoke从C#调用的dll方法中的可选struct
参数?例如,lpSecurityAttributes
parameter here不存在时应传递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
指向指针并调用该方法:
marshal the struct
在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)
。)
[如[[2)中使用creates a IntPtr.Zero
。对于非IntPtr.Zero
情况,只需声明一个选项:
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
版本(如上述2)
IntPtr.Zero
参数时,它将自动调用它。4)使用IntPtr
的原始指针>cStruct
关键字):unsafe
unsafe
情况下,您传递[DllImport("mydll.dll", OptionName = optionValue, ...)]
static unsafe extern int DLLFunction(CStruct* cStruct, ...);
,而在null
情况下仅传递&myCStruct
。与1)中一样,如果此可选参数为最后一个参数,则可以将参数声明为null
以在排除null
时自动传递CStruct* cStruct = null
。
感谢@dialer提出此方法。