COM自定义接口,成员函数指针参数被破坏

时间:2013-09-05 10:28:22

标签: winapi com

我几年来一直在使用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数据开头的指针,这些数据可能只是跨进程边界无法访问,但这并不能解释翻译。

1 个答案:

答案 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 pbcb中的数据需要编组到函数中,而pb表示BYTE的数组,这是cb个字节长。