如何处理使用 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?
class
而不是 struct
我认为这个方法是最简单的.只需将 struct
声明为 class
:
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
,当<时自动传null
code>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 结构参数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!