如何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

如何P/Invoke“__arglist”;作用

您需要使用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/…例如