2

イベントを発生させるWindowsランタイムコンポーネント(C#で記述)にクラスがあります。
コンポーネントを参照するC++/CXアプリでこれらのイベントをサブスクライブする方法を理解できません。

C#コード(Windowsランタイムコンポーネント内):

public sealed class Messenger {

    private EventRegistrationTokenTable<EventHandler<MessageReceivedEventArgs>> messageReceivedTokenTable;


public event EventHandler<MessageReceivedEventArgs> MessageReceived
{
    add
    {
        return EventRegistrationTokenTable<EventHandler<MessageReceivedEventArgs>>
            .GetOrCreateEventRegistrationTokenTable(ref this.messageReceivedTokenTable)
            .AddEventHandler(value);
    }

    remove
    {
        EventRegistrationTokenTable<EventHandler<MessageReceivedEventArgs>>
            .GetOrCreateEventRegistrationTokenTable(ref this.messageReceivedTokenTable)
            .RemoveEventHandler(value);
    }
}

internal void OnMessageReceived(string message, string location)
{
    EventHandler<MessageReceivedEventArgs> temp =
        EventRegistrationTokenTable<EventHandler<MessageReceivedEventArgs>>
        .GetOrCreateEventRegistrationTokenTable(ref this.messageReceivedTokenTable)
        .InvocationList;

    temp(this, new MessageReceivedEventArgs(message, location));
}

}

MessageReceivedEventArgsは:

public sealed class MessageReceivedEventArgs : object
{
    public MessageReceivedEventArgs(string message, string location)
    {
        this.Message = message;
        this.SenderLocation = location;
    }

    public string Message { get; set; }


    public string SenderLocation { get; set; }
}

MSDNによると、これはEventArgsではなくオブジェクトから派生していることに注意してください。

次にC++で:

msngr = ref new Messenger();

msngr->MessageReceived += ?????????

+=C ++アプリでメッセージを受信できるようにするには、関連するメソッド(およびその他の場所-C#および/またはC ++)の後に何を実行する必要がありますか?

私はさまざまなことを試しましたが、遭遇したさまざまなコンパイラの警告では、解決策を示すことができませんでした。

C#で記述されているがC ++アプリで使用されているWindowsランタイムコンポーネントの使用例はすべて些細なものであり、プロパティの使用とメソッドの呼び出しのみを示しています。どちらも問題なくできます。私は、C#で発生するC++のイベントをサブスクライブする例を示しています。

4

3 に答える 3

5

このようなタイプを使用するには、プロキシを作成する必要があります。

これは確かにあなたの問題です。MessageReceivedEventArgsクラスをC#からC ++ / CXにマーシャリングするには、COMプロキシ/スタブが必要です。そして、はい、非常に不十分に文書化されています。プロセスを説明するのに少し突き刺します。このWinRTサンプルを開始します。これは、必要なプロキシを取得するためのソリューションをセットアップする方法を示し、実行したいことを正確に実行します。

開始点は、共有クラスを宣言するC#プロジェクトであるProxyStubForWinRTComponents_serverプロジェクトです。プロジェクトの重要な部分はビルド後のイベントで、次のようになります。

call "$(DevEnvDir)..\..\VC\vcvarsall.bat" x86
winmdidl /outdir:"$(ProjectDir)\" "$(TargetPath)"

最初のステートメントは、SDKツールを実行するための環境をセットアップします。2番目のステップでは、プロジェクトによって生成された.winmdファイルをIDLファイルに逆コンパイルしてからコンパイルする完全に文書化されていないビルドツールであるwinmdidl.exeを実行します。このビルドステップの出力は次のとおりです。

  • Microsoft.SDKSamples.Kitchen.idl-IDL形式で逆コンパイルされた.winmdファイルであり、残りのファイルの生成に使用されます
  • Microsoft.SDKSamples.Kitchen.h-C ++ / CXプロジェクトに#includeするのに適した、C ++形式のC#タイプの宣言が含まれています
  • Microsoft.SDKSamples.Kitchen_i.c-プロキシの構築に使用されるC#タイプのGUIDが含まれています
  • Microsoft.SDKSamples.Kitchen_p.c-プロキシとスタブが生成されるgooが含まれています
  • dlldata.c-プロキシの構築に使用されます。

次に、Proxy/スタブDLLをビルドするProxyStubsForWinRTComponentsPSプロジェクトを見てください。これは、winmdidl.exeによって生成されたファイルを消費します。追加されたのは、DLLからのエクスポートを宣言する.defファイルだけです。COMはそれらを呼び出してプロキシを使用します。ファイルはそのまま使用できます。このプロジェクトをそのまま使用し、ファイルの名前のみを変更することをお勧めします。これにより、すべてのコンパイラーとリンカーの設定が正しくなります。

これを間違えるための不快で多くの方法は間違いありません。それが役に立てば幸い。

于 2013-02-10T21:30:45.720 に答える
1

このコードをC++refクラス、たとえばCPPClassで記述しているとすると、コードは次のようになります。

CPPClass::MyEventHandler(Platform::Object^ obj, MessageReceivedEventArgs^ args)
{
    // handler code
}


CPPClass::SomeMethod()
{
    msngr = ref new Messenger(this->SpecifedServer->Text);
    msngr->MessageReceived += ref new EventHandler<MessageReceivedEventArgs^>(this, &CPPClass::MyEventHandler);
}

=================

ちなみに、以下は私にとってうまく機能する同様のサンプルコードです:

C#でのクラスとイベントの定義:

namespace WindowsRuntimeComponent3
{
    public sealed class MyEventsArgs
    {
    }

    public sealed class Class1
    {
        public Class1()
        {
        }

        public event EventHandler<MyEventsArgs> MyEvent;
    }
}

C ++でイベントを消費する:

App::App()
{
    InitializeComponent();
    Suspending += ref new SuspendingEventHandler(this, &App::OnSuspending);

    auto obj = ref new WindowsRuntimeComponent3::Class1();
    obj->MyEvent += ref new EventHandler<WindowsRuntimeComponent3::MyEventsArgs^>(this, &App::MyEventHandler);
}

=================

于 2013-02-06T12:33:39.880 に答える
0

このシナリオの公式ドキュメントは、MSDNのここにあります:Windowsランタイムコンポーネントでのイベントの発生

于 2013-10-28T17:47:01.250 に答える