对VB6接口方法的后期绑定调用

Late-bound call to VB6 interface methods

本文关键字:绑定 调用 VB6 接口 方法      更新时间:2023-10-16

在我的C++程序中,我使用了一个在VB6 COM DLL中实现的COM类。让我们把这个类称为CETicketRA。此类具有类型为IPositionPromotion的属性AppliedPromotionIPositionPromotion是由相同的VB6 COM DLL定义的接口。它有各种各样的属性和方法,我试图从C++访问这些属性和方法。

给定以下代码:

IDispatch* pETicketRA = NULL;
DISPPARAMS dispParams = {0};
VARIANT result;
VariantInit(&result);
// Left out: some code to set pETicketRA ...
OLECHAR* strAppliedPromotion = L"AppliedPromotion";
DISPID dispIDAppliedPromotion = -1;
HRESULT hr = pETicketRA->GetIDsOfNames(IID_NULL, &strAppliedPromotion, 1, LOCALE_SYSTEM_DEFAULT, &dispIDAppliedPromotion);
hr = pETicketRA->Invoke(dispIDAppliedPromotion, IID_NULL, LOCALE_SYSTEM_DEFAULT, DISPATCH_PROPERTYGET, &dispParams, &result, NULL, NULL);
IDispatch* pPromo = NULL;
hr = result.pdispVal->QueryInterface(IID_IDispatch, reinterpret_cast<LPVOID*>(&pPromo));
VariantClear(&result);

现在我尝试读取IPositionPromotion:的属性Foobar

OLECHAR* strFoobar = L"Foobar";
DISPID dispIDFoobar = -1;
hr = pPromo->GetIDsOfNames(IID_NULL, &strFoobar, 1, LOCALE_SYSTEM_DEFAULT, &dispIDFoobar);

不幸的是,最后一次调用DISP_E_UNKNOWNNAME失败。

是否有人成功地从C++(或C#)调用了VB6接口成员?

VB6使用显式接口实现。实现接口的方法不会成为实现对象公共接口的一部分,为了调用它们,您需要显式地请求接口。如果你愿意,你可以稍后要求IDispatch退出该接口,但你需要先查询接口,因为你从对象本身得到的IDispatch和你从该对象实现的接口得到的IDispatch将是不同的IDispatches

所以当你有:

' IInterface.cls
Public Sub Method()
End Sub
' Class1.cls
Implements IInterface
Private Sub IInterface_Method()
  MsgBox "!"
End Sub

如果您想创建Class1的实例并调用Method(),则以下操作将不起作用:

' Complile-time error: method not found
Dim c As Class1
Set c = New Class1
c.Method
' Run-time error: Object does not support this property or method
Dim c As Object    ' IDispatch
Set c = New Class1 ' QueryInterface for IDispatch from Class1
c.Method

以下内容将起作用:

Dim c As IInterface
Set c = New Class1
c.Method  ' Early binding
Dim c As IInterface
Set c = New Class1
Dim c_as_idispatch As Object   ' IDispatch
Set c_as_idispatch = c         ' QueryInterface for IDispatch from IInterface
c.Method  ' Late binding

您的C++代码与上面的第二个不起作用的示例相同。

要解决此问题,请先用QueryInterface查找IPositionPromotion,然后查询IDispatch