对 VB6 接口方法的后期绑定调用
Late-bound call to VB6 interface methods
在我的 C++ 程序中,我使用了一个在 VB6 COM DLL 中实现的 COM class。我们称之为 class CETicketRA
。此 class 具有类型 IPositionPromotion
的 属性 AppliedPromotion
。 IPositionPromotion
是同一个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 使用显式接口实现。实现接口的方法不会成为实现对象的 public 接口的一部分,为了调用它们,您需要显式请求接口。如果愿意,您可以稍后从该接口中询问 IDispatch
,但您需要先查询接口,因为 IDispatch
是从对象本身获取的,而 IDispatch
是从接口获取的此对象实现的将是不同的 IDispatch
es.
所以当你有:
' 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
。
在我的 C++ 程序中,我使用了一个在 VB6 COM DLL 中实现的 COM class。我们称之为 class CETicketRA
。此 class 具有类型 IPositionPromotion
的 属性 AppliedPromotion
。 IPositionPromotion
是同一个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 使用显式接口实现。实现接口的方法不会成为实现对象的 public 接口的一部分,为了调用它们,您需要显式请求接口。如果愿意,您可以稍后从该接口中询问 IDispatch
,但您需要先查询接口,因为 IDispatch
是从对象本身获取的,而 IDispatch
是从接口获取的此对象实现的将是不同的 IDispatch
es.
所以当你有:
' 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
。