我几年来一直在使用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 \”示例代码替换了我自己的IFoo的IStream。
我可以在我的客户端代码中创建一个IFoo实例,但是成员函数'Bar'不起作用。我无法弄清楚为什么,看,当我打电话
IFoo->Bar( 0x42A110, 352 ); // address just an example
服务器端将参数视为
Bar( 0x560E20, 352 );
地址值并不重要,但这里的翻译是什么?帮助赞赏:)目前,我只是传递一个指向std::vector
数据开头的指针,这些数据可能只是跨进程边界无法访问,但这并不能解释翻译。
答案 0 :(得分:3)
通过COM边界传递的参数通常是编组的。这样做是因为COM边界可能是机器边界(在DCOM的情况下)或过程边界(在进程外COM组件的情况下)。 COM基础结构代表您执行此编组操作,所执行的操作将取决于所涉及的数据类型。如果您对细节感兴趣,请阅读公寓,编组和代理和存根(或查看COM IDL & Interface Design)。
鉴于您的参数需要编组,您接下来需要了解IDL如何声明函数的参数。您编写的IDL没有将足够的信息传递给MIDL编译器,以便正确生成代理和存根。 BYTE *pb
可以是单个字节或数组,值可以传递给函数或从函数返回...现在,我知道它是一个数组,因为我可以看到你有一个指定的长度,但MIDL不知道这一点。同样地,我猜测它的数据被传递到函数中,因为cb
不是一个指针,所以你不能告诉调用者你返回了多少数据但只传递了多大的数据是...告知MIDL它需要编组一些字节而不是只需要一个字节,你需要告诉它pb
是一个数组。你这样做:
HRESULT Bar(
[in, size_is(cb)] BYTE *pb,
[in] ULONG cb);
我们在这里做的是告诉MIDL pb
和cb
中的数据需要编组到函数中,而pb
表示BYTE的数组,这是cb
个字节长。