Riv*_*ver 13 c# null pinvoke interop optional-parameters
如何struct使用pinvoke 处理从C#调用的dll方法中的可选参数?例如,lpSecurityAttributes此处的参数应该null在不存在时传递.
正确的传递方式struct似乎正在使用ref,但它不能有可选参数,或者null总的来说.
有什么方法可以达到这个目的?
Riv*_*ver 16
class而不是astruct我认为这种方法最简单.只需声明struct为class:
[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显式传递.您还可以编写一个使用此方法的包装器方法,并确保可选参数最后.
IntPtr和IntPtr.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.)
使用struct如2) .
只需为非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参数时它会自动调用它.
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建议这种方法.