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

查看:120
本文介绍了如何处理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情况下,将结构编组指针并调用方法:

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情况:

[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,以便在排除cStruct时自动传递null.

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天全站免登陆