如何实现P/Invoke“__arglist”的功能?

How to P/Invoke "__arglist" function?

背景:
我用 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

我尝试了以下方法,但 returns 编译器错误:

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)不支持可变参数:

[DllImport("foo/bar.dll", EntryPoint = "test", 
           CallingConvention = CallingConvention.Cdecl)]
public static unsafe extern int __unmanaged__test(byte* buffer, __arglist);

另一个棘手的部分是 __arglist(...) 是一个编译时特性——它只是为它的每个 "arguments" 生成一个(虚拟)堆栈推送。这意味着您不能将它与编译时未知的参数一起使用 - 在您的示例代码中,您只是试图创建一个参数,键入 object[].

构建辅助反射方法并不难 - 请参阅 示例。我无法对此进行测试,但我猜 Expression 可用于轻松构建此代码 - 如果您不必通过 byte*,也就是说(您 真的 必须吗?通过 byte[] 也可以。

评论 Luuan wrote () 有我需要的解决方案:

引用:

If you need to build __arglist dynamically (that is, you don't know the types and amount of arguments in advance), you'll probably have to use reflection.
See for example