4

この質問で私の好ましい解決策は不可能であると言われた後、私は現在、回避策を実装しようとしています。C ++ / CXでIClosableから継承するインターフェイスを宣言する代わりに、生のIDLで宣言しています。しかし、それもうまくいかないようです。

FooSpace.idlを含むIDLファイルを作成しました

import "inspectable.idl";
import "Windows.Foundation.idl";
namespace FooSpace
{
    [uuid(01234567-89AB-CDEF-FEDC-BA9876543210)]
    [version(42)]
    interface Foo : IInspectable requires Windows.Foundation.IClosable
    {
    }
}

とそれからWindowsランタイムメタデータを生成します

midlrt /nomidl /metadata_dir "C:\Program Files (x86)\Windows Kits\8.0\References\CommonConfiguration\Neutral" FooSpace.idl

FooSpace.winmdを使用して分解すると、生成されたものは問題なく表示されますildasm。特に、システムが提供する場合とまったく同じように、Fooから継承しているように見えます。IClosableIInputStreamWindows.winmd

ただし、C ++ / CXから使用しようとすると、実装すらしていません。当面の間、他の誰かがWRLなどで実装したふりをして、機能しないようです。これが私のテストC++/CXソースファイルです。

void works(Windows::Storage::Streams::IInputStream^ istream) {
  Platform::IDisposable^ local = istream ;
}
void doesnt(FooSpace::Foo^ foo) {
  Platform::IDisposable^ local = foo ;
}

これはエラーを生成しますが、エラーは生成しFooませんIInputStream

C:\cygwin\tmp>cl /nologo /c /ZW /FU FooSpace.winmd  testit.cpp
testit.cpp
testit.cpp(5) : error C2440: 'initializing' : cannot convert from 'FooSpace::Foo ^' to 'Platform::IDisposable ^'
        No user-defined-conversion operator available, or
        Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast

私はここで何が間違っているのですか?


一方、同等のC#コードは正常にコンパイルされるようです。

public class Whatever {
  public static void Works(Windows.Storage.Streams.IInputStream istream) {
    System.IDisposable local = istream ;
  }
  public static void AlsoWorks(FooSpace.Foo foo) {
    System.IDisposable local = foo ;
  }
}
4

1 に答える 1

2

コマンドに mdmerge の呼び出しを追加すると、動作するはずです。

midlrt /nomidl /metadata_dir "C:\Program Files (x86)\Windows Kits\8.0\References\CommonConfiguration\Neutral" FooSpace.idl
mdmerge -metadata_dir "C:\Program Files (x86)\Windows Kits\8.0\References\CommonConfiguration\Neutral" -i "." -o "merged" -v -partial
cl /nologo /c /ZW /FU merged\FooSpace.winmd /EHsc testit.cpp

「マージされた」winmd ファイルを使用すると、次のようなコードをコンパイルできます。

namespace ClosableTest
{
    ref class Test sealed
        : FooSpace::Foo
    {
    public: 
        virtual ~Test()
        {
           FooSpace::Foo^ f = nullptr;
           Platform::IDisposable^ d = f;
        }
    };
}

midlrt によって生成された元の FooSpace.winmd ファイルは Windows.Foundation (C:\Windows\system32\WinMetadata\Windows.Foundation.winmd) を参照し、mdmerge の出力は Windows (C:\Program Files (x86)\Windows Kits\) を参照します。 8.0\References\CommonConfiguration\Neutral\Windows.winmd)。

ac# プロジェクトで mildrt-output の winmd ファイルを問題なく参照できたのは興味深いことです。なぜなら、ブログ投稿How to reference C++ WRL Components from a .NET project Kevin Stumpf が、最初に mdmerge を使用しない場合に問題があったと述べているからです。 .

于 2013-10-01T21:47:31.433 に答える