情况: 我有一个使用 P/Invoke 的非托管 (C++) DLL 的托管(C#、.NET 2.0)应用程序。除了“简单”方法(POD 参数/返回值)之外,还需要将 boost::variant 值数组传递给代码。原因是这些方法传递报表数据(类似于 Excel 单元格,可以是任何类型)。C# 代码接受它们作为装箱的“对象”。
以前的实现要求使用 COM VARIANT 的 SafeArray。但是,由于编码不佳/未对其进行测试,编组结果是内存泄漏。现在我必须找到另一个编组数据的选项。
以前的实现如下所示: C++:
extern "C" __declspec(dllexport) void GetReport(VARIANT& output) {
// ... here a SafeArray of VARIANT values was created
output.vt = VT_VARIANT | VT_ARRAY;
output.parray = safeArray;
}
C#
[DllImport("CppLibrary.dll")]
private static extern void GetReport(out object output);
//....
object data;
GetReport(data);
object rows = data as object[];
此特定实现通过不释放互操作结构来泄漏内存。
我试图通过包含 SafeArray 编组指令来更改原型:
C++
extern "C" __declspec(dllexport) void GetReport(SAFEARRAY output) { // Also tried SAFEARRAY*, SAFEARRAY&, VARIANT, VARIANT&, VARIANT*
// Internal stuff
}
C#
private static extern void GetReport([Out, MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_VARIANT)]ref object[] output);
但是,我实现的唯一事情是结果对象为空,或者由于内存损坏/堆栈溢出而崩溃。
问题: 如何正确地将此类数据类型(VARIANT 类型结构的数组)编组为 C#?我可以使 C++ DLL 成为 COM 的,但这需要重写相当多的代码。有没有更简单的方法摆脱这种情况?也许我错过了一些东西。