如何处理null或可选的DLL结构参数 [英] How do I handle null or optional DLL struct parameters
问题描述
如何在使用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屋!