How do I handle null or optional DLL struct parameters(如何处理 null 或可选的 DLL 结构参数)
问题描述
如何处理使用 pinvoke 从 C# 调用的 dll 方法中的可选 struct 参数?例如,lpSecurityAttributes 此处的参数 不存在时应传递null.
How do I deal with optional struct arguments in dll methods called from C# using pinvoke? For example, the lpSecurityAttributes parameter here should be passed null when absent.
struct 的正确传递方式似乎是使用ref,但它不能有可选参数,或者一般取null.
The correct way of passing struct's seems to be using ref, but it cannot have optional parameters, or take null in general.
有哪些方法可以实现这一目标?
What ways are there to achieve this?
推荐答案
你有几个选择
1) 使用 class 而不是 struct
我认为这个方法是最简单的.只需将 struct 声明为 class:
You have a few options
1) Use a class instead of a struct
I think this method is the easiest. Simply declare the struct as a class:
[StructLayout(LayoutKind.Sequential)]
public class CStruct
{
//member-list
}
然后声明你的方法:
[DllImport("mydll.dll", OptionName = optionValue, ...)]
static extern int DLLFunction(CStruct cStruct, ...);
如果您的可选参数恰好是最后一个,您可以使用 CStruct cStruct = null 作为参数.这允许您排除它而不是显式传递 null.您还可以编写一个使用此方法并确保可选参数放在最后的包装方法.
If your optional parameter happens to be the last one, you can instead use CStruct cStruct = null as the parameter. This allows you to exclude it instead of passing null explicitly. You can also write a wrapper method that uses this and ensures the optional parameters come last.
使用struct:
[StructLayout(LayoutKind.Sequential)]
public struct CStruct
{
//member-list
}
并将您的方法声明为:
[DllImport("mydll.dll", OptionName = optionValue, ...)]
static extern int DLLFunction(IntPtr cStruct, ...);
在非null 的情况下,编组struct 指向一个指针并调用该方法:
In the non-null case, marshal the struct to a pointer and call the method:
IntPtr ptr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(CStruct)));
try{
Marshal.StructureToPtr(myCStruct, ptr, false);
DLLFunction(ptr, ...);
} finally {
Marshal.FreeHGlobal(ptr);
}
在null的情况下,调用带有IntPtr.Zero的方法:
In the null case, call the method with IntPtr.Zero:
DLLFunction(IntPtr.Zero, ...);
同样,如果这恰好是列表中的最后一个(或者您使用包装器使其成为可选参数),您可以将此参数设为可选.通过使用 IntPtr cStruct = default(IntPtr) 作为参数来执行此操作.(作为 default(IntPtr) 创建一个 IntPtr.Zero.)
Again, you can make this parameter optional if this happens to be the last in the list (or you use a wrapper to make it so). Do this by using IntPtr cStruct = default(IntPtr) as the parameter. (As default(IntPtr) creates a IntPtr.Zero.)
使用 struct,如 2).
简单地为非null情况声明一个选项:
Simply declare one option for the non-null case:
[DllImport("mydll.dll", OptionName = optionValue, ...)]
static extern int DLLFunction(ref cStruct, ...);
另一个用于 null 的情况:
and another for the null case:
[DllImport("mydll.dll", OptionName = optionValue, ...)]
static extern int DLLFunction(IntPtr cStruct, ...);
第一个方法会在传递struct 时自动调用,第二个方法会在传递IntPtr.Zero 时自动调用.如果使用可选参数声明IntPtr 版本(如上面2)底部所示),它会在您排除cStruct时自动调用它代码>参数.
The first method will automatically get called when passing a struct, and the second when passing IntPtr.Zero. If declaring the IntPtr version with an optional parameter (as shown at the bottom of 2) above), it will automatically call it when you exclude the cStruct parameter.
使用 2) 中的结构并声明您的方法(注意 unsafe 关键字):
Use a struct as in 2) and declare your method (note the unsafe keyword):
[DllImport("mydll.dll", OptionName = optionValue, ...)]
static unsafe extern int DLLFunction(CStruct* cStruct, ...);
在非null 的情况下,您传递&myCStruct,并在null 中简单地传递null案件.和1)一样,如果这个可选参数在最后,你可以把参数声明为CStruct* cStruct = null,当<时自动传nullcode>cStruct 被排除在外.
In the non-null case, you pass &myCStruct, and simply null in the null case. As in 1), if this optional parameter is last, you can declare the parameter as CStruct* cStruct = null to automatically pass null when cStruct is excluded.
感谢@dialer 提出这种方法.
这篇关于如何处理 null 或可选的 DLL 结构参数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:如何处理 null 或可选的 DLL 结构参数
基础教程推荐
- C# 从 List<List<int>> 中删除重 2022-01-01
- Azure Functions:CosmosDBTrigger 未在 Visual Studio 中触发 2022-01-01
- .NET SerialPort DataReceived 事件未触发 2022-01-01
- 如果有人提交恶意软件Nuget包怎么办? 2022-01-01
- 当值可以是对象或空数组时反序列化 JSON 2022-01-01
- 禁止输入少量字符,例如'<'、'&a 2022-01-01
- 如何使用 .Net 检查 Active Directory 服务器是否已启动并正在运行? 2022-01-01
- WPF 模态进度窗口 2022-01-01
- Moq It.Is<>不匹配 2022-01-01
- 我应该在后面的代码中直接使用 Linq To SQL 还是使 2022-01-01
