【发布时间】:2008-10-18 11:56:04
【问题描述】:
我在 CPP 中有一个函数,原型如下:
char* complexFunction(char* arg1, ...);
我使用 DLLImport 属性从 C# 导入它。 问题是: 如何在 C# 中定义原型(在 DLLImport 属性下)? 我如何将参数传递给这个函数? 谢谢
【问题讨论】:
标签: c# c++ interop pinvoke variadic-functions
我在 CPP 中有一个函数,原型如下:
char* complexFunction(char* arg1, ...);
我使用 DLLImport 属性从 C# 导入它。 问题是: 如何在 C# 中定义原型(在 DLLImport 属性下)? 我如何将参数传递给这个函数? 谢谢
【问题讨论】:
标签: c# c++ interop pinvoke variadic-functions
这称为可变参数函数。对它们的 P/Invoke 支持的信息相当少,这是我发现的。
我找不到直接DllImport 具有可变数量参数的函数的方法。我不得不将DllImport 所有变体参数作为不同的重载。
我们以wsprintf 为例。它在winuser.h 中有如下原型:
int WINAPIV wsprintf(
LPTSTR lpOut,
LPCTSTR lpFmt,
...);
它可以像这样从 C# 中使用:
using System;
using System.Text;
using System.Runtime.InteropServices;
class C {
// first overload - varargs list is single int
[DllImport("user32.dll", CallingConvention=CallingConvention.Cdecl)]
static extern int wsprintf(
[Out] StringBuilder buffer,
string format,
int arg);
// second overload - varargs list is (int, string)
[DllImport("user32.dll", CallingConvention=CallingConvention.Cdecl)]
static extern int wsprintf(
[Out] StringBuilder buffer,
string format,
int arg1,
string arg2);
public static void Main() {
StringBuilder buffer = new StringBuilder();
int result = wsprintf(buffer, "%d + %s", 42, "eggs!");
Console.WriteLine("result: {0}\n{1}", result, buffer);
}
}
现在联系您的complexFunction。
char* complexFunction(char* arg1, ...);
它的可变参数列表应该以同样的方式处理:通过提供所有有用的重载。但是还有另一个复杂的地方——返回类型。我假设complexFunction 分配并返回char 的数组。在这种情况下,调用者很可能负责数组的释放。为此,您还应该导入解除分配例程,我们称之为void free(void*)。
假设所有这些,使用 complexFunction 的 C# 代码将如下所示:
using System;
using System.Text;
using System.Runtime.InteropServices;
class C {
[DllImport("your.dll",
CallingConvention=CallingConvention.Cdecl,
CharSet=CharSet.Ansi)]
static extern IntPtr complexFunction(
string format,
int arg1, int arg2);
[DllImport("your.dll", CallingConvention=CallingConvention.Cdecl)]
static extern void free(IntPtr p);
public static void Main() {
IntPtr pResult = complexFunction("%d > %s", 2, 1);
string sResult = Marshal.PtrToStringAnsi(pResult);
free(pResult);
Console.WriteLine("result: {0}", sResult);
}
}
【讨论】: