如何P/Invoke“__arglist”;作用
本文关键字:arglist 作用 Invoke 如何 | 更新日期: 2023-09-27 18:09:33
背景:
我用C++编写了以下函数:
extern "C" __declspec(dllexport) int test(const char*, ...);
我正在使用p/Invoke从C#调用它:
[DllImport("foo/bar.dll", EntryPoint = "test")]
public static unsafe extern int __unmanaged__test(byte* buffer, __arglist);
问题:
我需要动态初始化
__arglist
,这意味着我有一个Array<object>
,在调用C++函数之前,我必须将其转换为__arglist
。我尝试了以下操作,但它返回了一个编译器错误:
unsafe {
byte[] buffer = ....
object[] args = ....
// ....
fixed (byte* ptr = buffer)
return __unmanaged__test(ptr, __arglist(args)); // <--ERROR
}
有人知道解决这个问题的方法吗?
对于那些不知道
__arlist
是什么的人:http://bartdesmet.net/blogs/bart/archive/2006/09/28/4473.aspx
您需要使用C风格的调用约定-其他(包括默认的Stdecl(不支持varargs:
[DllImport("foo/bar.dll", EntryPoint = "test",
CallingConvention = CallingConvention.Cdecl)]
public static unsafe extern int __unmanaged__test(byte* buffer, __arglist);
另一个棘手的部分是__arglist(...)
是一个编译时特性——它只是为每个"参数"生成一个(虚拟(堆栈推送。这意味着您不能将它与编译时未知的参数一起使用——在示例代码中,您只是试图创建一个类型为object[]
的参数。
构建辅助反射方法并不太难——有关示例,请参阅通过DynamicMethod调用varargs方法。我无法测试这一点,但我想Expression
可以很容易地用来构建这段代码——如果你不必通过byte*
,也就是说(你真的必须通过吗?通过byte[]
也可以(。
Luuan写的评论(见此处(有我需要的解决方案:
报价:
如果您需要动态构建__arglist(也就是说,您事先不知道参数的类型和数量(,那么您可能必须使用反射
参见stackoverflow.com/questions/29458616/…例如