0

コールバックを許可するインターフェイスを受け入れるメソッドを持つ C++/ATL ベースの COM オブジェクトがあります。

MIDL

[object, uuid(...), dual, nonextensible, oleautomation, pointer_default(unique)]
interface IAsyncEvents : IDispatch{
    [id(1)]
    HRESULT OnProgress([in]BSTR message);
};

[object, uuid(...), dual, nonextensible, pointer_default(unique)]
interface IAsyncWorker : IDispatch{
    HRESULT CallMe(BSTR message, IAsyncEvents* events);
};

COM オブジェクトは IAsyncWorker インターフェイスを実装します。唯一のメソッド「CallMe」は、クライアントがワーカー スレッドからのコールバックを許可するために「events」インターフェイスを渡す必要があることを想定しています。「CallMe」の実装は次のようになります。

STDMETHOD(CallMe)(BSTR message, IAsyncEvents* events)
    {                       
        IStream *pStm = NULL;
        HRESULT hRes = CoMarshalInterThreadInterfaceInStream(IID_IAsyncEvents, events, &pStm);
        if (hRes != S_OK)
        {
            ATL::CAtlString str;
            str.Format(_T("Failed CoMarshallInterThread... %i"), hRes);
            MessageBox(0, str, NULL, MB_TOPMOST);
            return E_FAIL;
        }

        m_hThread = ::CreateThread(NULL, 0, WorkerFunc, (LPVOID)pStm, 0, &m_dwThreadId);
        return ::GetLastError();
    }

そして、次のように Visual Basic から「CallMe」を呼び出そうとします。

MyCallBack クラス

Option Explicit
Implements AsyncDllLib.IAsyncEvents

Public Sub IAsyncEvents_OnProgress(ByVal message As String)
    MsgBox (message)
End Sub

VB6 com オブジェクト呼び出しコード

Dim obj As Object
Set obj = CreateObject("C++ Com Object ProgID")

Dim callback As New MyCallbackClass

obj.CallMe "123", callback

すべて問題ないように見えますが、突然 MyCallback クラス インスタンスがストリームにマーシャリングされません。一方、同じスレッドの C++ 実装から「イベント」インターフェイス ポインターを使用できます。

CoMarshalInterThreadInterfaceInStream が文書化されていないエラーで失敗する: 0x800A0062

ここで何が間違っていますか?

前もって感謝します!

4

1 に答える 1

2

プライベート クラスをマーシャリングすることはできません。標準のマーシャリングでは、スレッド間で引数を転送するために typelib が必要です。

MyCallbackClassマーシャリングを機能させるために、VB6 の ActiveX DLL プロジェクトにパブリック (マルチユースまたはパブリック作成不可) クラスとして実装するか、ATL コンポーネントにコールバック プロキシをより適切に実装することができます。

元のVB6CallMeインターフェイスを渡す呼び出しスレッドでプロキシを作成し、IAsyncEventsプロキシ オブジェクトのインターフェイスをワーカー スレッドにマーシャリングします。

于 2012-05-02T11:53:59.887 に答える