【发布时间】:2012-05-08 20:03:10
【问题描述】:
我正在尝试通过 c# 完成这项工作:
C 头文件:
typedef void (LogFunc) (const char *format, va_list args);
bool Init(uint32 version, LogFunc *log)
C# 实现:
static class NativeMethods
{
[DllImport("My.dll", SetLastError = true)]
internal static extern bool Init(uint version, LogFunc log);
[UnmanagedFunctionPointer(CallingConvention.Cdecl, SetLastError = true)]
internal delegate void LogFunc(string format, string[] args);
}
class Program
{
public static void Main(string[] args)
{
NativeMethods.Init(5, LogMessage);
Console.ReadLine();
}
private static void LogMessage(string format, string[] args)
{
Console.WriteLine("Format: {0}, args: {1}", format, DisplayArgs(args));
}
}
这里发生的是对NativeMethods.Init 的调用回调LogMessage 并将来自非托管代码的数据作为参数传递。这适用于参数是字符串的大多数情况。但是,有一个调用的格式是:
为版本 %d 加载插件 %s。
并且 args 仅包含一个字符串(插件名称)。它们不包含版本值,这是有道理的,因为我在委托声明中使用了string[]。问题是,我应该如何编写委托来获取字符串和 int?
我尝试使用object[] args 并得到了这个异常:
在从非托管 VARIANT 转换为托管对象期间检测到无效 VARIANT。将无效的 VARIANT 传递给 CLR 可能会导致意外异常、损坏或数据丢失。
编辑: 我可以将委托签名更改为:
internal delegate void LogFunc(string format, IntPtr args);
我可以解析格式并找出预期的参数数量和类型。例如。对于 为版本 %d 加载的插件 %s。 我希望有一个字符串和一个 int。有没有办法从 IntPtr 中取出这两个?
【问题讨论】:
-
封送参数只是问题的一部分,您只能通过调用 vsprintf() 正确格式化字符串。您需要用 C++/CLI 语言编写一个小适配器。
标签: c# c++ pinvoke marshalling