0

ここ数週間、ABI レイヤーで WRL をいじっていて、この問題に遭遇しました。

IDL で次のように定義されたインターフェイスがあります。

namespace Async{
[uuid(f469e110-7ef5-41df-a237-9ddef9aed55c), version(1.0)]
interface IDownloader : IInspectable
{
    HRESULT GetFeed([in] HSTRING url,[out, retval] Windows.Web.Syndication.SyndicationFeed ** feed);
    [propget]HRESULT Feed([out, retval]Windows.Web.Syndication.SyndicationFeed ** feed);
}

[version(1.0), activatable(1.0)]
runtimeclass Downloader
{
    [default] interface IDownloader;
}

}

ヘッダーファイルで次のように定義しました:

#pragma once

#include "Async_h.h"

namespace ABI {
    namespace Async {


    class Downloader : public Microsoft::WRL::RuntimeClass<ABI::Async::IDownloader>
    {
        InspectableClass(L"Async.Downloader", BaseTrust);

    public:
        Downloader();
        STDMETHOD(GetFeed)(HSTRING url, ABI::Windows::Web::Syndication::ISyndicationFeed ** feed);
        STDMETHOD(get_Feed)(ABI::Windows::Web::Syndication::ISyndicationFeed ** feed);

    private:

        //Microsoft::WRL::ComPtr<ABI::Windows::Foundation::Uri> feedUrl;
        Microsoft::WRL::ComPtr<ABI::Windows::Web::Syndication::ISyndicationFeed> m_feed;

    };

    ActivatableClass(Downloader);
}

}

私のcppファイルでは、関数を実装しています:

    STDMETHODIMP Downloader::GetFeed(HSTRING url, ISyndicationFeed** feed)
    {

        HRESULT hr;
        RoInitializeWrapper ro(RO_INIT_MULTITHREADED);
        ComPtr<IUriRuntimeClass> uri;
        ComPtr<IUriRuntimeClassFactory> uriFactory;
        hr = GetActivationFactory(HStringReference(RuntimeClass_Windows_Foundation_Uri).Get(), &uriFactory);
        hr = uriFactory->CreateUri(url, uri.GetAddressOf());

        ComPtr<ISyndicationClient> client;
        ComPtr<IInspectable> inspectable;

        RoActivateInstance(HStringReference(RuntimeClass_Windows_Web_Syndication_SyndicationClient).Get(), &inspectable);

        hr = inspectable.As(&client);
        Event timerCompleted(CreateEventEx(nullptr, nullptr, CREATE_EVENT_MANUAL_RESET, WRITE_OWNER | EVENT_ALL_ACCESS));
        auto callback = Callback<IAsyncOperationWithProgressCompletedHandler<SyndicationFeed*,RetrievalProgress>>([&](IAsyncOperationWithProgress<SyndicationFeed*,RetrievalProgress> *op, AsyncStatus status) ->HRESULT 
        {
            auto error = GetLastError();
            if (status == AsyncStatus::Completed)
            {
                hr = op->GetResults(m_feed.GetAddressOf());
                *feed = m_feed.Get();

            }


            return S_OK;
        });
        ComPtr<IAsyncOperationWithProgress<SyndicationFeed*,RetrievalProgress>>  operation;
        hr = client->RetrieveFeedAsync(uri.Get(), operation.GetAddressOf());
        operation->put_Completed(callback.Get());
        return S_OK;
    }


    STDMETHODIMP Downloader::get_Feed(ISyndicationFeed** feed)
    {
        *feed = m_feed.Get();
        return S_OK;
    }

プロパティは期待どおりに機能し、本来あるべき c++/cx に投影されます。ただし、GetFeed メソッドで、取得したフィードにフィード パラメータを設定しようとすると、アクセス違反が発生します。明らかに、メモリが悪いことはわかっていますが、COM プロパティを理解する方法は、基本的に関数呼び出しであり、プロパティ メソッドと GetFeed メソッドは、検索部分を除いてまったく同じことを行っています。

ここに私の質問があります:

  1. 投影された戻り値がある場合、COM プロパティ メソッドと通常のインターフェイス メソッドの違いは何ですか?
  2. プロパティ メソッドへのパラメータが nullptr に初期化され、GetFeed メソッドへのパラメータが IDL でまったく同じように記述されているのに、なぜそうではないのですか?
  3. プロパティ メソッドの out パラメーターが初期化されている場合、COM ランタイムのどの部分がそれを実行しており、それは制御可能ですか? IE に書き込み可能なメモリを取得する方法はありますか?

おそらくそれを離れてデザインできることはわかっていますが、それは重要ではありません。私はそれがどのように機能するかを学ぼうとしています。

ありがとう。

4

1 に答える 1

1

あなたのラムダでは、 を参照してキャプチャしています[&]feedラムダが実行されるまでにスタック フレームがなくなってしまうため、パラメータを値でキャプチャする必要があります。

より大きな問題は、クライアントがその情報を提供しないため、いつ結果を取得できるかがわからないことです。(未使用の Win32 Event オブジェクトを作成しているのを見たので、それを機能させるための他のコードが削除されている可能性があります)。

于 2015-03-18T05:08:24.730 に答える