错误C2664'HRESULT IUnknown :: QueryInterfaceconst IID&,void **':无法将参数1从'const winrt :: guid'转换为'const IID&'

问题描述

当我使用microsoft docs to migrate to winrt from cx中的helper函数时,会发生此错误。我看到类似的问题here,但是提到的解决方案似乎对我不起作用。此处提到的解决方案在具有此错误文件中的任何其他winrt标头之前添加#include

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;
}

这是整个文件

#pragma once

#include <Unknwn.h>
#include <winrt/Windows.Foundation.h>

namespace x {
namespace y {

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;
}

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

解决方法

winrt::guid_of()返回一个winrt::guid。根据{{​​3}}:

  • 重大变化。 GUID现在投影为winrt::guid。对于实现的API,必须对GUID参数使用winrt::guid。否则,winrt::guid会转换为GUID,只要您包含unknwn.h,然后再包含任何C ++ / WinRT标头。参见What's new in C++/WinRT

Interoperating with the ABI's GUID struct

GUID投影为winrt::guid。对于您实现的API,必须对winrt::guid参数使用GUID。否则,只要您包含winrt::guid(由和许多其他头文件隐含),在包含任何内容的GUIDunknwn.h 之间会自动进行转换。 C ++ / WinRT标头

如果您不这样做,则可以在它们之间进行强行reinterpret_cast

因此,请确保在WinRT标头之前包含unknwn.h,或者可以显式reinterpret_cast,例如:

template <typename T>
T from_cx(Platform::Object ^ from) {
    T to{nullptr};
    winrt::guid iid = winrt::guid_of<T>();

    winrt::check_hresult(
        reinterpret_cast<::IUnknown*>(from)->QueryInterface(
            reinterpret_cast<GUID&>(iid),reinterpret_cast<void**>(winrt::put_abi(to)))
    );

    return to;
}
,

IInspectable的评论也对我有用:

如果您#include ,请确保在添加之前确实包含它 任何winrt标头。使用预编译头文件时,您可以在其中 还必须包括Unknwn.h。

...至关重要的是,您的编译单元必须包含Unknwn.h 在任何其他winrt头文件之前。编译单元通常有一个 .cpp,.cc或.cxx的文件扩展名。

我认为标头必须包含在定义这些辅助函数的文件中。