Передать объект класса ref (Uri^) в качестве параметра собственного указателя (IUriRuntimeClass *)

В моем коде есть следующий метод midl:

interface IMyClass : IInspectable { HRESULT Func1([in] Windows.Foundation.Uri *uri); }

Он генерирует следующий метод интерфейса:

IMyClass : public IInspectable { public:virtual HRESULT STDMETHODCALLTYPE Func1( /* [in] */ __RPC__in_opt ABI::Windows::Foundation::IUriRuntimeClass *uri) = 0; }

Интерфейс реализован на стороне приложения, и его объект передается в мой код, где я могу "видеть" только интерфейс.
Я хочу знать, как лучше позвонить Func1 и передать Windows::Foundation::Uri объект как параметр?

Простая передача объекта класса ref не работает из-за ошибки C2664
Windows::Foundation::Uri^ u = ref new Uri(...); IMyClassObj->Func1(u); // error cannot convert argument 1 from Windows::Foundation::Uri ^' to 'ABI::Windows::Foundation::IUriRuntimeClass *

Я мог бы достичь своей цели с помощью reintrepret_casting:
Windows::Foundation::Uri^ u = ref new Uri(...); ABI::Windows::Foundation::IUriRuntimeClass* uu = reinterpret_cast<ABI::Windows::Foundation::IUriRuntimeClass*>(u); MyClassObj->Func1(u); // this works fine

Является ли reinterpret_cast правильным подходом в этой ситуации? Или есть какой-то другой способ передачи объекта Uri^ в качестве параметра IUriRuntimeClass*?

1 ответ

Решение

Немного более чистый способ сделать это, чтобы обернуть его в 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());
}
Другие вопросы по тегам