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