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

标签 c# null interop pinvoke optional-parameters

如何处理使用 pinvoke 从 C# 调用的 dll 方法中的可选 struct 参数?例如,lpSecurityAttributes parameter here不存在时应传递 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案例,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) creates a IntPtr.Zero 。)

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

使用 struct2)

只需为非 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。自动传递 null什么时候cStruct被排除在外。

感谢@dialer 推荐此方法。

关于c# - 如何处理 null 或可选的 DLL 结构参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47997942/

相关文章:

用于根据范围查找当前项目的 C# 数据结构

c# - C# 中的数据绑定(bind)()

java - 为什么返回空集合被认为是好的做法?

c# - 通过 COM 互操作访问 C# 中的 protected 内存

c# - "Win32Exception: The operation completed successfully"在 32 位 Windows 上的 WTSQueryUserToken 之后(64 位有效)

ClojureScript 互操作

c# - 带输入字段的 FolderBrowserDialog

c# - 在 Observable.FromAsyncPattern 上优雅地处理超时

c# - 将 "Null"或 "None"成员添加到枚举中是一种好的做法吗?

.net - F# null 测试未能检测到 null 值