我正在尝试为现有(黑盒子)客户端学习并重新实现(黑盒子)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
参数中设置的数据?
答案 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 []。