0

タイプ ライブラリで定義され、コードに実装されたカスタム インターフェイスがあります。独自のプロキシ/スタブを作成していません。私の場合はIGlobalInterfaceTableを使用して、インターフェイス ポインターをメイン スレッド (STA) からバックグラウンド スレッド (STA) に正常にマーシャリングしました。

そのバックグラウンド スレッドから、UI スレッドでオブジェクトへの非同期呼び出しを行いたいと考えています。オブジェクトにICallFactoryを実装していません。標準プロキシが実際にICallFactoryを実装していることがわかります (つまり、 ICallFactoryのバックグラウンド スレッドで正常に QI を実行できます)。しかし、カスタム インターフェイスのCreateCallは HRESULT 0x80040150 (レジストリからキーを読み取ることができませんでした) で失敗します。

これを行うには、 ICallFactoryを明示的に実装する独自のプロキシを作成する必要がありますか?

ここに私のIDLがあります:

[
    object,
    uuid(92303FE7-A79D-47DD-923F-62062105C00E),
    async_uuid(2880C40C-9965-4544-AE39-DF08056E8CB6),
    nonextensible,
    pointer_default(unique),
    oleautomation
]
interface IFoo: IUnknown
{
    HRESULT Foo([in] long a, [in] long b);
}

[
    uuid(D58B0A31-A2D5-4BFB-8702-3B710320493B)
]
coclass Foo
{
    [default] interface IFoo;
};

そして、これが私の単体テストのバックグラウンド スレッド プロシージャです。

    static DWORD WINAPI threadproc(LPVOID lpParameter)
    {
        // get arguments
        DWORD cookie = *(DWORD*)lpParameter;

        // initialize COM
        Assert::AreEqual(S_OK, CoInitializeEx(NULL, COINIT_APARTMENTTHREADED));
        {
            // get global interface table
            IGlobalInterfaceTablePtr globalInterfaceTable;
            Assert::AreEqual(S_OK, globalInterfaceTable.CreateInstance(CLSID_StdGlobalInterfaceTable));

            // get object
            MyLib::IFooPtr object;
            Assert::AreEqual(S_OK, globalInterfaceTable->GetInterfaceFromGlobal(cookie, MyLib::IID_IFoo, (LPVOID*)&object));

            // get async call factory
            ICallFactoryPtr callFactory;
            Assert::AreEqual(S_OK, object->QueryInterface(&callFactory));

            //
            // Everything is fine up until the CreateCall call below,
            // which fails with HRESULT 0x80040150
            //

            // create async call object
            IUnknownPtr callObject;
            Assert::AreEqual(S_OK, callFactory->CreateCall(MyLib::IID_AsyncIFoo, NULL, IID_IUnknown, &callObject));
        }
        // uninitialize COM
        CoUninitialize();

        // success
        return 0;
    }

4

1 に答える 1

0

私の知る限り、ユニバーサル マーシャラーは Async COM では機能しません。(MIDL で生成された) プロキシを構築する必要があります (ただし、IIRC では、DLL を構築している場合はスタブをマージできます)。

また、プロキシ DLL を登録する (および -DREGISTER_PROXY_DLL 定義でビルドする) 必要があります。Async COM を機能させるには、さらに多くのレジストリ キーを定義する必要があります。

于 2015-05-14T21:53:21.103 に答える