将 ref class object(Uri^) 作为本机指针参数 (IUriRuntimeClass *) 传递
pass ref class object(Uri^) as native pointer parameter(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;
}
接口是在App端实现的,它的对象被传递到我的代码中,我只能'see'接口。
我想知道调用 Func1
并将 Windows::Foundation::Uri
对象作为参数传递的最佳方法是什么?
简单地传递 ref class 对象是行不通的,因为 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* 参数传递?
一种稍微简洁的方法是尽快将其包装在 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());
}
我的代码中有以下 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;
}
接口是在App端实现的,它的对象被传递到我的代码中,我只能'see'接口。
我想知道调用 Func1
并将 Windows::Foundation::Uri
对象作为参数传递的最佳方法是什么?
简单地传递 ref class 对象是行不通的,因为 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* 参数传递?
一种稍微简洁的方法是尽快将其包装在 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());
}