1

我正在将我的项目从 C++/CX 移植到 C++/WinRT。为此,我需要做一些这样的互操作:https ://docs.microsoft.com/en-us/windows/uwp/cpp-and-winrt-apis/interop-winrt-cx 。

Microsoft 建议使用这些帮助函数来实现互操作性。

from_cx 和 to_cx 函数 下面的帮助函数将 C++/CX 对象转换为等效的 C++/WinRT 对象。该函数将 C++/CX 对象转换为其底层 IUnknown 接口指针。然后,它在该指针上调用 QueryInterface 以查询 C++/WinRT 对象的默认接口。QueryInterface 是与 C++/CX safe_cast 扩展等效的 Windows 运行时应用程序二进制接口 (ABI)。而且,winrt::put_abi 函数检索 C++/WinRT 对象的基础 IUnknown 接口指针的地址,以便可以将其设置为另一个值。

template <typename T>
T from_cx(Platform::Object^ from)
{
    T to{ nullptr };

    winrt::check_hresult(reinterpret_cast<::IUnknown*>(from)
        ->QueryInterface(winrt::guid_of<T>(),
            reinterpret_cast<void**>(winrt::put_abi(to))));

    return to;
}

下面的帮助函数将 C++/WinRT 对象转换为等效的 C++/CX 对象。winrt::get_abi 函数检索指向 C++/WinRT 对象的基础 IUnknown 接口的指针。在使用 C++/CX safe_cast 扩展查询请求的 C++/CX 类型之前,该函数将该指针转换为 C++/CX 对象。

template <typename T>
T^ to_cx(winrt::Windows::Foundation::IUnknown const& from)
{
    return safe_cast<T^>(reinterpret_cast<Platform::Object^>(winrt::get_abi(from)));
}

但是,当我做这样的事情时:

auto text = winrt::Windows::UI::Xaml::Controls::TextBlock();
Windows::UI::Xaml::FrameworkElement^ cx = to_cx<Windows::UI::Xaml::FrameworkElement^>(text);

我收到一个错误:

没有函数模板“to_cx”的实例与参数列表匹配

参数类型是:(winrt::Windows::UI::Xanl::Controls::TextBlock)

但我确实看到 TextBlock 继承自 IUnknown。我错过了什么?

4

1 回答 1

2

将 winrt::UI::Xaml::Controls::TextBlock 对象转换为 C++/CX 对象

如果要将C++/WinRT对象移植C++/CX对象。您可以为解决方案制作 Windows 运行时组件(C++/WinRT)项目并将转换代码放入其中。然后让C++/WinRT项目引用上面的 Component(在 Solution Explorer 中右键单击C++/WinRT项目名称,单击 Add,选择 References,在 Add Reference 对话框中的 Projects 下选择刚刚添加的组件名称)。

笔记

您需要在 Windows 运行时组件(C++/WinRT) 项目中使用Consume Windows Runtime Extension>Yes(/ZM)而不是 C++/WinRT 项目。

然后,在 Windows 运行时组件 ( C++/WinRT ) 中,添加 cx 命名空间和 winrt 命名空间,以区分使用不同语言的不同对象。

以下代码可以放入您的组件项目的类中。

添加所需的标题,例如:

#include <winrt/Windows.UI.Xaml.Controls.h>
#include <winrt/Windows.UI.Xaml.h>

In the cx namespace, add  using statements:
namespace cx
{
    using namespace Windows::Foundation;
    using namespace Windows::UI::Xaml;
}

// And, in the winrt namespace, add the needed using statements:

namespace winrt
{
    using namespace Windows;
    using namespace Windows::ApplicationModel::Core;
    using namespace Windows::Foundation;
    using namespace Windows::Foundation::Numerics;
    using namespace Windows::UI;
    using namespace Windows::UI::Core;
    using namespace Windows::UI::Composition;
    using namespace winrt::Windows::UI::Xaml::Controls;
    using namespace winrt::Windows::UI::Xaml;
}
Add the to_cx method:
template <typename T>
T^ to_cx(winrt::Windows::Foundation::IUnknown const& from)
{
    return safe_cast<T^>(reinterpret_cast<Platform::Object^>(winrt::get_abi(from)));
}

//Change the code:

/*auto text = winrt::Windows::UI::Xaml::Controls::TextBlock();
Windows::UI::Xaml::FrameworkElement^ cx = to_cx<Windows::UI::Xaml::FrameworkElement^>(text);*/

auto text = winrt::Windows::UI::Xaml::Controls::TextBlock();
        cx::FrameworkElement^ cx = to_cx<cx::FrameworkElement>(text);

请注意 :

请不要将转换代码放入 XAML 页面,因为您的 XAML 页面类型需要完全是 C++/CX 或完全是 C++/WinRT。你可以在同一个项目中混合 XAML 页面类型之外的 C++/CX 和 C++/WinRT。

使用组件工程类中转换代码的函数必须先在类的idl文件中声明,否则不能在其他工程中引用该函数。

更新:

下面是我创建的一个简单示例,当点击主项目中的按钮时,我调用了 Windows 运行时组件的方法来触发 to_cx 方法,你可以查看它。

于 2020-08-07T07:47:21.440 回答