为什么在VB6中COM接口名被coclass名称所取代?

5

我正在开发一个C++ COM库,以便从VB6应用程序中使用它。.IDL文件定义了一些接口和一个类库,其中包含一些组件类,这些组件类实现了这些接口:

[
    local,
    object,
    uuid(....),
    version(1.0)
]
interface ICOMCvPixelBuffer : IUnknown
{
    ....
};

[
    local,
    object,
    uuid(....),
    version(1.0)
]
interface ICOMCvBitmap : IUnknown
{
    ....
    HRESULT GetPixelBuffer([retval][out] ICOMCvPixelBuffer** pBuffer);
    HRESULT SetPixelBuffer([in] ICOMCvPixelBuffer* pBuffer);
    ....
};

[
    uuid(....),
    version(1.0)
]
library COMCvLibrary
{
    importlib("stdole32.tlb");
    interface ICOMCvBitmap;
    interface ICOMCvPixelBuffer;

    [
        uuid(....),
        version(1.0)
    ]
    coclass CCOMCvPixelBuffer
    {
        [default] interface ICOMCvPixelBuffer;
    };

    [
        uuid(....),
        version(1.0)
    ]
    coclass CCOMCvBitmap
    {
        [default] interface ICOMCvBitmap;
    };
};

在VB6中的对象浏览器中,CCOMCvBitmap类的SetPixelBuffer方法的定义显示为Sub SetPixelBuffer(pBuffer As CCOMCvPixelBuffer)。为什么它不是在.IDL中声明的Sub SetPixelBuffer(pBuffer As ICOMCvPixelBuffer)
2个回答

4

最终我找到了我的问题的答案。

根据书籍《.NET和COM:完全的互操作指南》的理解,如果coclass的默认接口在与coclass相同的类库中定义,则VB6的类型库导入器将使用coclass类型替换默认接口类型的任何参数和字段。

另外,有关VB6背后的机制的有用信息可以在这里找到:

Visual Basic使用类模块名称作为默认接口的别名;也就是说,Visual Basic编译器会为您自动将类名静默映射到默认接口引用。

其中一个可行的解决方案是将IUnknown作为CCOMCvPixelBuffer coclass的默认接口提供:

[
    uuid(....),
    version(1.0)
]
coclass CCOMCvPixelBuffer
{
    [default] interface IUnknown;
    interface ICOMCvPixelBuffer;
};

太高兴了,我找到了这个答案!应该将其标记为被接受的答案。这种行为也会出现在tlbimp和C#中。 - sourcenouveau

2
据我所记,VB6不喜欢COM对象实现两个或以上的自动化接口。此外,如果它只实现一个,则很可能这个接口是由声明为实现此接口的coclass实现的:

coclass CCOMCvBitmap{ [default] interface ICOMCvBitmap; }

这样做可以让VB6开发人员更容易理解,试图使用对象而不是接口来解释工作原理。
如果您想尝试一下实验,请注释上面的“[default] interface ICOMCvBitmap;”这行,看看VB6是否会将类型显示为接口。这不应该破坏交互操作,因为您的ATL实现对象仍将实现IProvideClassInfo并广告实现的接口。

没错,就是这样。另一个惯例是在名称前加下划线来隐藏接口类型,例如_ICOMCvPixelBuffer。 - Hans Passant

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接