0

I have C++/ATL-based COM object with method that accepts interface to allow callbacks:

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 Object implements IAsyncWorker interface. The only method "CallMe" expects that client should pass "events" interface to allow callbacks from worker thread. "CallMe" implementation looks like the following:

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();
    }

And I try to call "CallMe" from Visual Basic like that:

MyCallBack Class

Option Explicit
Implements AsyncDllLib.IAsyncEvents

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

VB6 com-object call code

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

Dim callback As New MyCallbackClass

obj.CallMe "123", callback

Everything looks ok but suddenly MyCallback class instances fail to be marshalled into stream. Meanwhile I can use "events" interface pointer from C++ implementation from the same thread.

CoMarshalInterThreadInterfaceInStream fails with undocumented error: 0x800A0062

What I do wrong here?

Thank you in advance!

4

1 回答 1

2

You cannot marshal private classes, standard marshaling needs a typelib to transport arguments cross-thread.

You can implement MyCallbackClass as a public (multi-use or public-not-creatable) class on an ActiveX DLL project in VB6 for marshaling to work or better implement a callback-proxy in your ATL component.

Your CallMe will create the proxy on the calling thread passing original VB6 interface then marshal IAsyncEvents interface of proxy object to worker-thread.

于 2012-05-02T11:53:59.887 回答