如何处理 null 或可选的 DLL 结构参数 [英] How do I handle null or optional DLL struct parameters

查看:22
本文介绍了如何处理 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 结构参数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆