在COM方法中设置SAFARRAY输出参数

时间:2014-09-05 08:28:11

标签: c# com interop

我正在尝试为现有(黑盒子)客户端学习并重新实现(黑盒子)COM服务器。我通过导入类型库并创建实现服务器接口的.NET类来成功registered一个虚拟实现。

我有一个有问题的签名,在客户端调用时似乎不起作用:

这是IDL定义:

[id(0x00000007), helpstring("method GetFoo")]
HRESULT GetFoo(VARIANT* vector);

导入的.NET定义:

[DispId(7)]
void GetFoo(ref object vector);

注意:vector参数是输出参数。

客户端可以成功调用实现此接口的服务器。在此调用期间,我可以看到vector参数包含16个字节的数组。但是,似乎数组中的数据I设置未正确发送到客户端。我对原始服务器进行了逆向工程,并找到了它对参数所期望的确切VARIANT标志。使用这些信息,我创建了一个C ++客户端,在调用原始服务器时获取输出参数中的数据:

const int TABLE_LENGTH = 16;
SAFEARRAY* table = SafeArrayCreateVector(VT_I1, 0, TABLE_LENGTH);

VARIANT val; VariantInit(&val);
val.vt = VT_BYREF | VT_ARRAY | VT_I1 | VT_NULL;
val.pparray = &table;
realServer->GetFoo(&val); 
// now table contains valid data

如果我使用此客户端来呼叫我的服务器,那么在之前我会得到一个SafeArrayTypeMismatchException ,方法中的断点就会被命中。

我的问题是:如何实现.NET方法,以便上述客户端获取我在ref参数中设置的数据?

1 个答案:

答案 0 :(得分:1)

您必须传递VARIANT才能让服务器满意。那是.NET程序中的 object 。所以它必须看起来像这样:

object arg = null;
realServer.GetFoo(ref arg);
byte[] data = (byte[])arg;

IDL编写得不好,这个论点应该归因于[out,retval]。通常表明你会遇到更多问题。数组的另一个问题是它们的第一个元素可能是索引1而不是0。你可以在调试器中看到的东西, arg 变量看起来像System.Byte[*]。在这种情况下,您必须转换为Array而不是byte []。