【问题标题】:How to convert an existing customized SwapChainPanel from C++/CX to C++/WinRT如何将现有的自定义 SwapChainPanel 从 C++/CX 转换为 C++/WinRT
【发布时间】:2023-04-11 06:47:01
【问题描述】:

我正在尝试将我现有的 C++/CX 代码转换为 C++/WinRT,以确定这是否能让我使用 Clang 编译该代码。但是,我很早就被困住了。

我需要转换的 C++/CX 代码用于构建 Direct3D 组件(基于 SwapChainPanel),该组件最终在用 C# 编写的 Windows UWP 应用程序中使用。我面临的问题是我无法将自定义的SwapChainPanel 转换为 C++/WinRT。

代码如下:

namespace Why::Does::This::Not::Work
{
  [Windows::Foundation::Metadata::WebHostHidden]
  public ref class BaseView : public Windows::UI::Xaml::Controls::SwapChainPanel
  {
  protected private:
    BaseView();
    // Lots of other stuff
  };
}


namespace Why::Does::This::Not::Work
{
  [Windows::Foundation::Metadata::WebHostHidden]
  public ref class CustomView sealed : public BaseView
  {
  public:
    CustomView();
    // ...

    event AnimationEventHandler^ AnimationStarted;

  private protected:
    // Lots of private protected stuff
  };
}


namespace Why::Does::This::Not::Work
{
  [Windows::Foundation::Metadata::WebHostHidden]
  public ref class AnimationEventArgs sealed
  {
  public:
    AnimationEventArgs() {}

    AnimationEventArgs(int start, int end)
    {
      Start = start;
      End   = end;
    }

    property int Start;
    property int End;
  };

  [Windows::Foundation::Metadata::WebHostHidden]
  public delegate void AnimationEventHandler(Platform::Object^ sender, AnimationEventArgs^ e);
}

就我能够解释文档而言,我需要执行文档中If you're authoring a runtime class to be referenced in your XAML UI 下所述的操作。

因此,在我看来,我需要编写一个 IDL 文件才能生成所需的 COM 内容。但是,我什至无法编译骨架 IDL:

namespace Why
{
  namespace Does
  {
    namespace This
    {
      namespace Not
      {
        namespace Work
        {
          runtimeclass CustomView : Windows::UI::Xaml::Controls::SwapChainPanel
          {
            CustomView();
          }
        }
      }
    }
  }
}

当我试图编译上面的代码时,我得到的只是

error MIDL2025: [msg]syntax error [context]: expecting { near ":"
error MIDL2026: [msg]cannot recover from earlier syntax errors; aborting compilation

如果您认为这是一个愚蠢的问题,我深表歉意。我已经阅读了相应的文档,但我只是无法理解使用 C++/WinRT 时到底发生了什么。我在 C++ 方面有丰富的经验,但在 COM 方面的经验为零,这意味着理解 C++/WinRT 并非易事。

如果有人可以帮我将上述 C++/CX 代码翻译成 C++/WinRT,我将不胜感激。请不要只将我指向文档,这没有帮助。


编辑:

修改示例IDL代码如下成功编译:

namespace Why
{
  namespace Does
  {
    namespace This
    {
      namespace Not
      {
        namespace Work
        {
          [default_interface]
          runtimeclass CustomView : Windows.UI.Xaml.Controls.SwapChainPanel
          {
            CustomView();
          }
        }
      }
    }
  }
}

但是,将用户控件暴露给另一种语言,在我的例子中是 C#,例如从 SwapChainPanel 继承的语言,比在 C++/CX 中做同样的事情要复杂得多。有一个 IDL 处理起来并不容易,因为周围似乎没有任何复杂的样本。该 IDL 生成了几个头文件,我不确定如何处理这些头文件,因为缺少文档并且示例很少。 C++/WinRT 不适合胆小的人,与 C++/CX 相比,它的复杂性要高得多。

在我看来,真正了解 C++/WinRT 有必要很好地掌握 COM,因为与 C++/CX 相比,C++/WinRT 在隐藏这些 COM 方面做得很差相关内部。在处理 DirectX 时尤其如此。再加上一个 IDL,它本身就很难处理,它的文档可能足以启动和运行简单的示例,但在移植完整的 C++/CX 应用程序时没有多大帮助。

在 C++/WinRT 中使用 C++/CX 做我们所做的事情并不经济,我们将继续使用 C++/CX,直到 C++/WinRT 变得更加更加用户友好。消除对 IDL 的需求(请参阅 https://wpdev.uservoice.com/forums/110705-universal-windows-platform/suggestions/36095386-get-rid-of-idl-for-c-winrt-components)也会有所帮助。

如果没有能够使用 Clang 编译我们的代码的前景,我什至不会考虑离开 C++/CX。微软不应该怀疑 C++/WinRT 的采用速度很慢。如果他们真的想改变,他们必须大大降低进入门槛。

【问题讨论】:

  • 写了几十年的COM代码,我这里可能有点偏颇。但是,我的看法是,C++/WinRT 在隐藏所有 COM 基础方面做得非常。您永远不会看到任何QueryInterfaceAddRefRelease 调用,您也不会接触到类型激活或工厂实现的细节。事实上,它把 COM 隐藏得太多了:当你通过值传递 MyType 时,它取决于命名空间,是通过值传递实现类型,还是指向实现类型的智能指针,语义上与传递相同-by-ref.
  • 不过,C++/WinRT 一种具有挑战性的 Windows 运行时方法。进入的障碍可能看起来巨大,但它真的不是那么糟糕,一旦你玩了一段时间。我现在正在进行我的第二个 C++/WinRT 玩具项目,感觉就像编写 C# 代码,但具有 C++ 的灵活性和原始功能。我的建议:继续玩。
  • 感谢您的 cmets。在这里获得其他意见会很有帮助,因为很难看到未来会发生什么。鉴于我们的时间限制,我只需要看看我能做些什么。

标签: c++-winrt


【解决方案1】:

IDL 中的完全限定类型名称使用句点 (.) 作为命名空间分隔符。一个有效的 IDL 文件如下所示:

namespace Why
{
  namespace Does
  {
    namespace This
    {
      namespace Not
      {
        namespace Work
        {
          runtimeclass CustomView : Windows.UI.Xaml.Controls.SwapChainPanel
          {
            CustomView();
          }
        }
      }
    }
  }
}

Microsoft Interface Definition Language 3.0 reference 有相当完整的文档。即便如此,从 MIDL 错误消息中理解任何意义通常也是一项挑战。

【讨论】:

  • 感谢您的回复。编译您提供的修改后的示例导致 MIDL 编译器错误error MIDL5053: [msg]empty runtime class cannot have the [composable] or [activatable] attribute [context]: [ RuntimeClass 'Why.Does.This.Not.Work.CustomView' ]。然后我在您在这里发表的评论中看到了该错误消息:stackoverflow.com/a/50845563。这导致我在解决错误的runtimeclass 代码行上方添加[default_interface] 属性。但是,现在我收到以下错误(请参阅下一条评论)
  • error MIDL2212: [msg]error while writing to file [context]SetViewTest.winmd (HRESULT:0x80070003 - The system cannot find the path specified. )。我验证了与 .idl 文件关联的设置,并将它们与 PhotoEditor 示例应用程序和新创建的 Windows 运行时组件 Visual Studio 项目中使用的设置进行了比较,它们完全匹配。不知道这里发生了什么,我迷路了。
  • 嗯,没关系。当我清除所有构建输出并从头开始重建所有内容时,该错误消息就消失了。到目前为止一切顺利,一旦我知道更多,我会回到这个问题。
猜你喜欢
  • 1970-01-01
  • 2020-12-17
  • 2015-10-25
  • 2021-04-05
  • 2020-11-27
  • 2011-11-25
  • 1970-01-01
  • 2016-01-04
  • 1970-01-01
相关资源
最近更新 更多