从非托管代码调用具有可变数量参数的.NET函数

时间:2009-12-10 12:07:36

标签: .net c++

我想用可变数量的参数调用C#函数:

void f1(object arg1, params object[] argsRest);

来自非托管,带有包装f1的可变参数的C函数。

如何实现这一目标?

4 个答案:

答案 0 :(得分:1)

从C开始,您需要将数组的长度作为参数传递给C#,这样您就可以将指向数组的指针封送到c#数组中。我不认为你可以直接使用C中的那个函数签名。

答案 1 :(得分:1)

要公开托管功能,您需要编写一个充当桥梁的混合模式DLL(您应该阅读MSDN上的this文章作为背景。)

您的c ++ - cli桥DLL将包含类似于以下内容的代码...

#include <cstdarg>

extern "C" {
    __declspec(dllexport) void f1wrapper(void *arg1, int nargs, ...)
    {
        array<Object^>^ managedArgs = gcnew array<Object^>(nargs);
        va_list args;
        va_start(args, nargs);
        for (int _i = 0; _i < nargs; ++_i)
        {
            managedArgs[_i] = ???; // <- you need to translate args
        }
        va_end(args);

        // Call your function
        Object^ managedArg1 = ???; // <- translate arg1
        f1(managedArg1, managedArgs);
    }
}

然后链接混合模式DLL并从C代码调用f1wrapper(...)。不完整,但应该为您提供足够的实验基础。

答案 2 :(得分:0)

params object[]基本上只是一个数组,因此将其视为数组。

答案 3 :(得分:0)

谢谢,我已经实现了这个目标。

在C函数中:

void UnmanagedClass::foo(int i, char *message, ...);

在排除期间,变量'i'和消息将被放在堆栈上,然后是附加参数数组的地址。

我在一个CLR项目中存在混合的非托管/托管代码,具有可变数量参数的函数将被编译为非托管函数(here)。这就是我用成员函数创建桥类的原因:

void ManagedClass::foo(int i, char * message, unsigned int *params);

并实施:

void UnmanagedClass::foo(int i, char *message, ...) {
    unsigned int *p = (unsigned int*) &message;
    p++;
    ManagedClass::foo(i, message, (unsigned int) p);
}

我不需要多个参数,因为'message'以printf方式提供有关参数的数量和类型的信息。

这样,在'ManagedClass :: foo()'函数中,我解析了数组'p',创建了相应托管类型的实例,将它们排列在objects数组中,并将它们传递给具有不变数量参数的托管方法。 / p>