2016-07-28 12 views
0

私のC++プログラムでは、VB6 COM DLLに実装されているCOMクラスを使用します。このクラスをCETicketRAと呼ぶことにしましょう。このクラスは、タイプIPositionPromotionAppliedPromotionというプロパティを持っています。 IPositionPromotionは、同じVB6 COM DLLによって定義されたインターフェイスです。それは私がC++からアクセスしようとする様々なプロパティとメソッドを持っています。次のコードを考えるVB6インターフェイスメソッドへの遅延バインドコール

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で失敗します。

VB6インターフェイスメンバーをC++(またはC#)から呼び出すことに成功した人はいますか?

+0

C#では、「ダイナミック」でVB6スタイルにすることができます。 C++の場合、http://stackoverflow.com/q/11670175/11683が役立ちます。 – GSerg

+0

COM規則がより厳格であるかどうかは不明ですが、通常は実行時にオブジェクトにアクセスしようとすると動的エラーを引き起こす関数の名前が変更されます。 _IF_の場合は、必要に応じて 'extern" C "'にしてください。 – M4rc

+0

@GSerg:私はすでにダイナミックにしようとしましたが、動作しません。しかし、私は何かを見つけました。VB6 COM DLLでは、 'IPositionPromotion'を実装するクラスで、' IPositionPromotion'インターフェースを実装するメソッドは通常 'Private'として宣言されます。彼らは 'IPositionPromotion_Foobar'という名前です。私が 'Private'から' Public'に変更した場合、 'pPromo'オブジェクトに対して' IPositionPromotion_Foobar'を呼び出すことができます。 しかし、これはかなり醜い "解決策"です。 –

答えて

0

VB6は明示的なインターフェイスの実装を使用します。実装されたインタフェースのメソッドは、実装オブジェクトのパブリックインタフェースの一部にはならず、それらを呼び出すには、インタフェースを明示的に要求する必要があります。もしあなたが望むのであれば、IDispatchを後でそのインターフェイスから尋ねることができますが、IDispatchはオブジェクト自体から取得し、IDispatchはこのオブジェクトによって実装されたインターフェイスから取得するので、IDispatchは異なるでしょう。

だからあなたが持っているとき:

' 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++コードは、上記第二の非実施例と同一です。

QueryInterfaceIPositionPromotionに変更するには、IDispatchを削除してください。

+0

小さな調整でうまくいきました。 C++で、 'IDispatch'から派生した' IPositionPromotion'インターフェースを宣言しました。ProgIDはコクラスのCLSIDを参照するため、OleViewを使用してインターフェイスのIIDを取得しました。この組み合わせでは、実際に 'QueryInterface'に' IPositionPromotion'の 'result.pdispVal'オブジェクトを渡すことができます。次に、私は実際に 'QueryInterface'を' IDispatch'のためにこれを実行できます。このオブジェクトは 'Foobar'メソッドを知らないのですが、なぜ' IPositionPromotion'インターフェースを使用できるのか 'IDispatch'を使うべきですか?私はそれを使って 'フーバー'と呼ぶことができます。 ありがとう! –