【问题标题】:How to declare interface that inherits from IClosable/IDisposable如何声明继承自 IClosable/IDisposable 的接口
【发布时间】:2013-01-17 04:13:03
【问题描述】:

this question 被告知我首选的解决方案是不可能的后,我现在正在尝试实施一种解决方法。我没有在 C++/CX 中声明从 IClosable 继承的接口,而是在原始 IDL 中声明它。但这似乎也不起作用。

我创建了一个 IDL 文件 FooSpace.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

当我用ildasm 反汇编生成的FooSpace.winmd 时,它看起来还不错——尤其是Foo 似乎继承自IClosable,就像IInputStream 在系统提供的Windows.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 ;
  }
}

【问题讨论】:

    标签: windows-runtime c++-cx


    【解决方案1】:

    如果您将 mdmerge 调用添加到您的 cmd,它应该可以工作:

    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 工具包\8.0\References\CommonConfiguration\Neutral\Windows.winmd)。

    有趣的是,您能够毫无问题地引用 c# 项目中的 midrt-output winmd 文件,因为在博客文章 How to reference C++ WRL Components from a .NET projectKevin Stumpf 中描述了他在不先使用 mdmerge 时遇到了一些问题。

    【讨论】:

      猜你喜欢
      • 2019-07-16
      • 1970-01-01
      • 2012-05-17
      • 1970-01-01
      • 2011-02-26
      • 1970-01-01
      • 1970-01-01
      • 2010-12-22
      • 2012-03-20
      相关资源
      最近更新 更多