【发布时间】:2010-11-17 12:57:55
【问题描述】:
我有一个带有这个签名的 C++ 方法:
STDMETHODIMP ClassName::FunctionName(long number, BSTR* names, long* status)
在方法内部,names 变量作为字符串数组访问,即
char * tempString = NULL;
for (int n = 0; n < number; n++)
{
tempString = OLE2T(names[n]);
...
我编译 C++ 项目,生成一个 dll,然后注册这个 dll 并在 VB 项目中添加对它的引用。 当我添加引用时,会自动生成一个Interop程序集,Interop程序集中的方法签名如下:
FunctionName (number as Integer, ByRef names as String) As Integer
从 VB.Net 我调用这样的方法:
result = FunctionName (number, names(0))
其中names是一个包含多个元素的字符串数组,number和result是整数。
问题在于,当 C++ 代码尝试访问 names 数组中的其余元素(names[1] 及前面)时,它开始在这些字段上获得“垃圾”。
我的问题是,如何发送整个字符串数组而不仅仅是第一个值。
C++ 代码是一个我无法修改的库,因此我所做的任何更改都必须在 VB.Net 代码上。
我在想也许使用 PInvoke 来调用该方法可能会成功(声明正确的签名),但我希望有更好的东西。
有什么想法吗?
谢谢!
编辑:
我不是 Interop/Marshaling 方面的专家,但我检查了该方法的 IDL 定义,如下所示:
[id(60), helpstring("method FunctionName")]
HRESULT FunctionName(
[in] long number,
[in, size_is(number)] BSTR* names,
[out, retval] long* status);
size_is不应该表明names参数是一个数组,因此在生成Interop程序集时会采取相应的行动吗?
再次感谢
【问题讨论】:
-
您需要一些特殊的 IDL 指令来告诉 COM 编组器
number表示字符串数组names的大小。否则编组器不知道这一点,只需要独立的值,根本不知道names是一个数组。当然你可以编写一个 C++ 包装器,它“知道”原始 C++ 库的无效行为,并更正接口。 -
感谢您的及时回答,我刚刚用您所说的所需的 idl 信息编辑了问题。有什么建议吗?
-
VB 没有 p/invoke 或
MarshalAsAttribute,也许你的意思是 VB.net?names[0]也不是 VB 中的数组元素语法吗?解决问题的最简单方法是使用接受 .NETarray<String^>的 C++/CLI 包装器,转换为BSTR的数组,然后调用 C++ 函数。 -
是的,Ben,我指的是 VB.Net,数组的东西是一个错字,我刚刚修复了它。那么,有没有办法避免这个包装?我宁愿使用 Hans 方法(手动编辑 IL 并生成新的 Interop 程序集)。
标签: c++ vb.net interop marshalling