繁体   English   中英

使用P / Invoke编组VARIANT数组

[英]Marshalling arrays of VARIANT using P/Invoke

情况:我有一个托管(C#,. NET 2.0)应用程序,它使用P / Invoke使用非托管(C ++)DLL。 除了“简单”方法(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,但这需要重写相当少量的代码。 有没有更简单的方法摆脱这种情况? 也许我错过了什么。

有这个例子: http//limbioliong.wordpress.com/2011/03/20/c-interop-how-to-return-a-variant-from-an-unmanaged-function/

最后他们直接使用IntPtr (他们使用它作为返回值,你必须使用它作为out IntPtr ),然后来自C#端的Marshal.GetObjectForNativeVariant()VariantClear()Marshal.FreeCoTaskMem()而在C / C ++方面, VARIANT被分配了CoTaskMemAlloc()

[DllImport("MyDLL.dll", CallingConvention = CallingConvention.StdCall)]
static extern void MyFunction(out IntPtr ptr);

[DllImport("oleaut32.dll", SetLastError = true, CallingConvention = CallingConvention.StdCall)]
static extern Int32 VariantClear(IntPtr pvarg);

IntPtr pVariant;
MyFunction(out pVariant);

object objRet = Marshal.GetObjectForNativeVariant(pVariant);

VariantClear(pVariant);
Marshal.FreeCoTaskMem(pVariant);

pVariant = IntPtr.Zero;

很明显,你可以在你的dll中暴露另一个C函数来释放VARIANT (在你的库中暴露Free方法总是正确的,这样调用者就可以使用它们而不是问自己“我该如何释放这个内存?”)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM