c++uwpc++-cxmidl

pass ref class object(Uri^) as native pointer parameter(IUriRuntimeClass *)


I have following midl method in my code:

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

It generates following interface method:

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

The interface is implemented in App side and its object is passed to my code where I can 'see' only interface.
I want to know what is the best way to call Func1 and pass Windows::Foundation::Uri object as parameter?

Simply passing ref class object does not not work, due to C2664 error
Windows::Foundation::Uri^ u = ref new Uri(...); IMyClassObj->Func1(u); // error cannot convert argument 1 from Windows::Foundation::Uri ^' to 'ABI::Windows::Foundation::IUriRuntimeClass *

I could achive my goal with 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

Is reinterpret_cast right approach in this situation? Or is there any other way of passing Uri^ object as IUriRuntimeClass* parameter?


Solution

  • A slightly cleaner way to do this is to wrap it in a ComPtr as soon as possible so you get the right behaviour if any exceptions are thrown etc. (Your method might be simple today, but it could get more complex later on).

    Something like this:

    #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());
    }