我的应用程序涉及托管(C#)和非托管(C ++)代码之间的大量通信。我们使用的是Visual Studio 2005(!),我们使用tlbimp自动生成的互操作程序集。
我们有很好的运气来回传递简单的结构作为函数参数。因为我们的对象非常简单,我们可以使用IRecordInfo接口将它们打包到SAFEARRAY中。将这些数组作为参数传递给COM方法似乎可以正常工作。
我们希望能够在我们的UDT中嵌入可变长度数组,但这很糟糕。我不认为我能找到一份文件显示某人是如何完成这项工作的。我也没有找到说无法完成的文档。
1)天真的方法:只需在托管代码中声明一个safearray:
struct MyUdt {
int member1;
BSTR member2;
SAFEARRAY *m3;
};
C ++编译器对此感到满意,但生成的IDL使tblimp.exe感到困惑。它报告它无法转换成员m3的签名,以及成员tagSAFEARRAY.rgsabound的签名。这些只是警告,但它们是有意义的,生成的程序集不可用。
奇怪的是,使用LPSAFEARRAY会以不同的方式失败,但出于同样的原因,tblimp无法处理它。
2)Trickier:将其打包成一个变体:
struct MyUdt {
int member1;
BSTR member2;
VARIANT m3;
};
我们有构建UDT安全阵列的代码,它从来没有给我们带来任何麻烦。它基本上是从MSDN复制的。使用该代码创建一个safearray,然后:
pVal->m3.vt = VT_SAFEARRAY | VT_RECORD;
pval->parray = p;
以奇怪的方式失败。它总是打破,一些变化产生一个OutOFMemoryException ......奇怪,其他变化以不同的方式失败。 (我不确定这里是否需要pRecInfo指针,但它的失败方式是相同的,无论是否存在。)
谷歌的搜索空间受到了严重的污染,我不会回答问题:
许多答案描述了如何从管理方面定义事物,而不是非管理方面。
然后有几个Microsoft KB在早期版本的.NET中描述了VT_RECORD的问题。我不认为这些是密切相关的 - VT_RECORD类型适用于VARIANT和SAFEARRAY。 (但也许不是UDT编组......)
如果这不起作用,至少知道原因会很好。