我想用可变数量的参数调用C#函数:
void f1(object arg1, params object[] argsRest);
来自非托管,带有包装f1的可变参数的C函数。
如何实现这一目标?
答案 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>