Reputation: 81
I have C/C++ SDK library which should be ported to Windows 8 Metro (WinRT). Library is mostly OS-independent, but it contains some modules which interact with hardware using OS-provided APIs.
While porting it to WinRT I've decided to try to use WRL instead of C++/CX as much as possible. So right now I can create and consume most of the required WinRT objects. But I've faced absolute obstacle while working with Async objects, provided by WinRT.
For example, I use following code to enumerate HW devices:
// create interface to "static" members of DeviceInformation class
ComPtr<IDeviceInformationStatics> DeviceInformationStatics;
HRESULT hr = GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Devices_Enumeration_DeviceInformation).Get(), &DeviceInformationStatics);
ComPtr<IAsyncOperation<DeviceInformationCollection*>> operation;
hr = DeviceInformationStatics->FindAllAsyncDeviceClass( DeviceClass_All, &operation);
At this point I have valid IAsyncOperation pointer. I thought it can be used like that:
task<ComPtr<DeviceInformationCollection*>> tsk(operation);
but I failed, because task<> constructor which accepts IAsyncOperation is declared under "#if defined(__cplusplus_winrt)" in ppltasks.h, which, in turn, depends on /ZW compiler option.
How I'm supposed to use IAsyncOperation object in this case? Actually, I only need to wait for operation to be completed.
Upvotes: 4
Views: 7675
Reputation: 2199
Just in case someone else is looking for this in C++/WinRT:
auto asyncOp = someFunctionReturningIAsyncOperation();
asyncOp.Completed([](auto &&result, auto && status) {
// do whatever with result and status
});
Upvotes: 4
Reputation: 770
This is an old question... But in case anyone needs the answer like I did:
The MSDN documentation shows how to accomplish this in native C++. It's pretty straightforward. You initialize the WRL runtime, the object you're interested in and then create an event and callback handler that will be called when the event fires.
Upvotes: 1
Reputation: 11
IAsyncOperation is an awaitable type, so you should you use the equivalent of await, or call it's Result property.
Upvotes: -1
Reputation: 61361
From my C++/CX experience, what you can do is you can construct an AsyncOperationCompletedHandler<DeviceInformationCollection*>
object, initialize it with a member function in your class, and assign it to the Completed
property of the IAsyncOperation.
In C++/CX, you just construct the AsyncOperationCompletedHandler<>
object with two parameters - this
from the calling class, and a pointer-to-member to a callback method. Like this:
MyAsyncOp->Completed = ref new AsyncOperationCompletedHandler<ResultType ^>(this, &MyClass::OnDone);
where OnDone is defined thus:
void MyClass::OnDone(IAsyncOperation<ResultType ^> ^AsOp, AsyncStatus s)
{
ResultType ^Result = AsOp->GetResults();
}
I'm not sure how to call constructors in WRL. You figure this one out.
Also, the completion handler will be called on a random thread. If you need to pass something back to the UI thread, Dispatcher->RunAsync()
is your friend. Most XAML classes have a Dispatcher member in them.
EDIT: now that I'm looking at samples, there seems to be a non-managed helper class called Callback
that you construct around a this
and a pointer-to-member. Look it up. Still not sure how to connect one to an IAsyncOperation though...
Upvotes: 1
Reputation: 283634
If the library hardware-specific module already works on Win32, I suggest you keep it that way. Install a Win32 service to interact with the hardware, and then the Metro app just needs to communicate with the service (many IPC options, such as sockets, pipes, I'm sure you can find one that works well even in the restricted Metro sandbox).
Upvotes: 0