C++ 将ref类对象(Uri^)作为本机指针参数传递(IUriRuntimeClass*)

C++ 将ref类对象(Uri^)作为本机指针参数传递(IUriRuntimeClass*),c++,uwp,c++-cx,midl,C++,Uwp,C++ Cx,Midl,我的代码中有以下midl方法: 接口IMyClass:IInspectable { HESREST函数([in ] Windows .Buffo.URI*URI); } 它生成以下接口方法: IMyClass:公共IIinspectable { 公共:虚拟HRESULT STDMETHODCALLTYPE Func1( /*[in]*/_RPC__in_opt ABI::Windows::Foundation::IUriRuntimeClass*uri)=0; } 该接口在应用程序端实现,其对

我的代码中有以下midl方法:

接口IMyClass:IInspectable
{ 
HESREST函数([in ] Windows .Buffo.URI*URI);
}

它生成以下接口方法:

IMyClass:公共IIinspectable
{
公共:虚拟HRESULT STDMETHODCALLTYPE Func1(
/*[in]*/_RPC__in_opt ABI::Windows::Foundation::IUriRuntimeClass*uri)=0;
}

该接口在应用程序端实现,其对象被传递到我的代码中,我只能“看到”该接口。
我想知道调用
Func1
并将
Windows::Foundation::Uri
对象作为参数传递的最佳方法是什么

由于C2664错误,仅传递ref类对象不起作用
Windows::Foundation::Uri^u=ref新Uri(…);
IMyClassObj->Func1(u);//错误无法将参数1从Windows::Foundation::Uri^'转换为“ABI::Windows::Foundation::IUriRuntimeClass”*

我可以通过reintrepret_铸造来实现我的目标:
Windows::Foundation::Uri^u=ref新Uri(…);
ABI::Windows::Foundation::IUriRuntimeClass*uu=reinterpret\u cast(u);
MyClassObj->Func1(u);//这个很好用


在这种情况下,重新解释是正确的方法吗?或者有没有其他方法可以将Uri^对象作为IUriRuntimeClass*参数传递?

一种稍微干净一点的方法是尽快将其封装在
ComPtr
中,以便在抛出任何异常时获得正确的行为等(您的方法今天可能很简单,但以后可能会变得更复杂)

大概是这样的:

#include <wrl/client.h>
#include <windows.foundation.h>

// Dummy method that just prints out the URI to the debug console
HRESULT MyFunc(ABI::Windows::Foundation::IUriRuntimeClass* uri)
{
    HSTRING str{};
    HRESULT ret{ S_OK };
    if (SUCCEEDED(ret = uri->get_AbsoluteUri(&str)))
        OutputDebugString(WindowsGetStringRawBuffer(str, nullptr));

    WindowsDeleteString(str);
    return ret;
}

void Test()
{
    using namespace Microsoft::WRL;

    // Create the ref class
    auto uri = ref new Windows::Foundation::Uri(L"http://www.bing.com");

    // Wrap in a dummy IUnknown wrapper. In theory you could use 
    // IInspectable or even IUriRuntimeClass but if you're going to 
    // copy-paste the code elsewhere, IUnknown is the "safest" thing you
    // can reinterpret_cast<>() to.
    ComPtr<IUnknown> iUnknown{ reinterpret_cast<IUnknown*>(uri) };

    // Try to cast it to the IUriRuntimeClass, and call our method if 
    // it succeeds
    ComPtr<ABI::Windows::Foundation::IUriRuntimeClass> iUri{};
    if (SUCCEEDED(iUnknown.As(&iUri)))
        MyFunc(iUri.Get());
}
#包括
#包括
//只将URI打印到调试控制台的伪方法
HRESULT MyFunc(ABI::Windows::Foundation::IUriRuntimeClass*uri)
{
HSTRING str{};
HRESULT ret{S_OK};
if(成功(ret=uri->get_AbsoluteUri(&str)))
OutputDebugString(WindowsGetStringRawBuffer(str,nullptr));
WindowsDeleteString(str);
返回ret;
}
无效测试()
{
使用名称空间Microsoft::WRL;
//创建ref类
自动uri=ref新窗口::基础::uri(L)http://www.bing.com");
//用一个虚拟的IUnknown包装器包装。理论上你可以使用
//IInspectable甚至IUriRuntimeClass但是如果你想
//把代码复制粘贴到别处,IUnknown是你最“安全”的东西
//可以将_cast()重新解释为。
ComPtr iUnknown{reinterpret_cast(uri)};
//尝试将其强制转换为IUriRuntimeClass,并在以下情况下调用我们的方法
//它成功了
ComPtr iUri{};
if(成功(iUnknown.As(&iUri)))
MyFunc(iUri.Get());
}

一种稍微简洁的方法是尽快将其包装在
ComPtr
中,以便在抛出任何异常时获得正确的行为等(您的方法今天可能很简单,但以后可能会变得更复杂)

大概是这样的:

#include <wrl/client.h>
#include <windows.foundation.h>

// Dummy method that just prints out the URI to the debug console
HRESULT MyFunc(ABI::Windows::Foundation::IUriRuntimeClass* uri)
{
    HSTRING str{};
    HRESULT ret{ S_OK };
    if (SUCCEEDED(ret = uri->get_AbsoluteUri(&str)))
        OutputDebugString(WindowsGetStringRawBuffer(str, nullptr));

    WindowsDeleteString(str);
    return ret;
}

void Test()
{
    using namespace Microsoft::WRL;

    // Create the ref class
    auto uri = ref new Windows::Foundation::Uri(L"http://www.bing.com");

    // Wrap in a dummy IUnknown wrapper. In theory you could use 
    // IInspectable or even IUriRuntimeClass but if you're going to 
    // copy-paste the code elsewhere, IUnknown is the "safest" thing you
    // can reinterpret_cast<>() to.
    ComPtr<IUnknown> iUnknown{ reinterpret_cast<IUnknown*>(uri) };

    // Try to cast it to the IUriRuntimeClass, and call our method if 
    // it succeeds
    ComPtr<ABI::Windows::Foundation::IUriRuntimeClass> iUri{};
    if (SUCCEEDED(iUnknown.As(&iUri)))
        MyFunc(iUri.Get());
}
#包括
#包括
//只将URI打印到调试控制台的伪方法
HRESULT MyFunc(ABI::Windows::Foundation::IUriRuntimeClass*uri)
{
HSTRING str{};
HRESULT ret{S_OK};
if(成功(ret=uri->get_AbsoluteUri(&str)))
OutputDebugString(WindowsGetStringRawBuffer(str,nullptr));
WindowsDeleteString(str);
返回ret;
}
无效测试()
{
使用名称空间Microsoft::WRL;
//创建ref类
自动uri=ref新窗口::基础::uri(L)http://www.bing.com");
//用一个虚拟的IUnknown包装器包装。理论上你可以使用
//IInspectable甚至IUriRuntimeClass但是如果你想
//把代码复制粘贴到别处,IUnknown是你最“安全”的东西
//可以将_cast()重新解释为。
ComPtr iUnknown{reinterpret_cast(uri)};
//尝试将其强制转换为IUriRuntimeClass,并在以下情况下调用我们的方法
//它成功了
ComPtr iUri{};
if(成功(iUnknown.As(&iUri)))
MyFunc(iUri.Get());
}

您是直接调用C++类还是正在调用WiMD元数据?MIDL和方法调用在同一个模块的组件中。所以这个电话是直拨电话。虽然接口实现是通过应用程序端的winmd完成的,其对象被传递回“组件”。您应该能够使用
ComPtr
并从
ref
类获取接口。在模块中,如果你只通过本地C++类型,通常是比较容易的。如果我的理解正确,我希望使用<代码> RealTytCase将<代码> URI^ 对象转换成<代码> COMPTR < /代码>。那么,在转换为<代码> COMPTR < /C>和使用本地指针时,在我的问题正文中有什么不同?您是直接调用C++类还是直接调用WiMD元数据?MIDL和方法调用在同一个模块的组件中。所以这个电话是直拨电话。虽然接口实现是通过应用程序端的winmd完成的,其对象被传递回“组件”。您应该能够使用
ComPtr
并从
ref
类获取接口。在模块中,如果你只通过本地C++类型,通常是比较容易的。如果我的理解正确,我希望使用<代码> RealTytCase将<代码> URI^ 对象转换成<代码> COMPTR < /代码>。那么,转换成ComPtr与使用本机指针(如我在问题正文中给出的示例)之间有什么区别呢?