0

我已经使用 COM 几年了,但从来没有写过接口,所以这让我有点困惑。

我有一个接口,让它被调用IFoo,定义为

import "unknwn.idl";
[
    object,
    uuid( // guidgen generated one // ),
] interface IFoo : IClassFactory
{
    HRESULT Bar(const BYTE * pb, ULONG cb );
};

我使用 MIDL 生成的文件编译并注册到 Windows 注册表中。我还制作了一个本地 COM 服务器,它基本上实现了 IFoo。在此,我遵循“Microsoft SDKs\Windows\v7.0\Samples\com\fundamentals\dcom\simple\”示例代码,将 IStream 替换为我自己的 IFoo。

我可以在我的客户端代码中创建一个 IFoo 实例,但成员函数“Bar”不起作用。我不知道为什么,看,当我打电话时

IFoo->Bar( 0x42A110, 352 ); // address just an example

服务器端将参数视为

Bar( 0x560E20, 352 );

地址值并不重要,但这里的翻译是什么?帮助表示赞赏:) 目前,我只是传递一个指向 a 数据开头的指针,std::vector这些数据可能无法跨进程边界访问,但这并不能解释翻译。

4

1 回答 1

3

跨 COM 边界传递的参数通常是编组的。这样做是因为 COM 边界可能是机器边界(在 DCOM 的情况下)或进程边界(在进程外 COM 组件的情况下)。COM 基础结构代表您执行此编组,所做的工作将取决于所涉及的数据类型。如果您对细节感兴趣,请阅读 Appartments、Marshalling 和 Proxies and Stubs(或查看COM IDL 和接口设计)。

鉴于您的参数需要编组,您接下来需要了解 IDL 如何将参数声明给您的函数。您编写的 IDL 没有将足够的信息传递给 MIDL 编译器以正确生成代理和存根。这BYTE *pb可以是单个字节或数组,值可以传递给函数或从函数返回......现在,我知道它是一个数组,因为我可以看到你在它后面指定了一个长度,但 MIDL 没有不知道。同样,我猜它传递给函数的数据cb不是指针,所以你不能告诉调用者你返回了多少数据,而只能告诉调用者传入的数组有多大......pb是一个数组。你这样做:

HRESULT Bar(
   [in, size_is(cb)] BYTE *pb,
   [in] ULONG cb);

我们在这里所做的是告诉 MIDL 两者中的数据都pb需要cb编组到函数中,它pb表示一个cb字节长的 BYTE 数组。

于 2013-09-05T10:50:03.233 回答