windows-rs icon indicating copy to clipboard operation
windows-rs copied to clipboard

Support for creating collections

Open kennykerr opened this issue 4 years ago • 9 comments

Many APIs assume the caller will provide a collection of values. This should integrate with winrt::Param to allow regular Rust collections and iterators to bind to WinRT input parameters of WinRT collection types.

kennykerr avatar Apr 28 '20 18:04 kennykerr

This depends on #81

kennykerr avatar Apr 28 '20 18:04 kennykerr

Many APIs assume the caller will provide a collection of values. This should integrate with winrt::Param to allow regular Rust collections and iterators to bind to WinRT input parameters of WinRT collection types.

Is there any workaround for this? I am trying to create a windows::ai::machine_learning::TensorFloat. It has a create2 constructor function which requires a Param<IIterable<i64>> as input .

Ideally I would like to call TensorFloat::create2([1,2,3]). If I could create an IVector v somehow, I could maybe do something like TensorFloat::create2(v.get_view().into()) but the single_threaded_vector function does not seem to be available in Rust.

rookboom avatar Jan 12 '21 21:01 rookboom

As a workaround, you can create a WinRT component with C++/WinRT that creates and returns the collection and then call that from Rust. You can even just have a component that returns an empty collection that you can then populate using Rust.

kennykerr avatar Jan 12 '21 21:01 kennykerr

As a workaround, you can create a WinRT component with C++/WinRT that creates and returns the collection and then call that from Rust. [...]

Hey @kennykerr, is this still a current workaround? Just hit this myself, needing an IVector<IRandomAccessStream>.

riverar avatar Jun 09 '21 17:06 riverar

Yes, this is still blocked on #81 where I need to add support to implement generic interfaces. Right now, the implement macro will only let you implement non-generic interfaces. I hope to get to this soon.

kennykerr avatar Jun 09 '21 17:06 kennykerr

Hey @kennykerr , is this still blocked? #81 is now closed. Granted, it did spin off a few other issues. I just need some way to pass an IIterable of HSTRINGs from Rust to wintrt. I'm hoping a year of progress has yielded at least a work around at this point that doesn't involve C++.

GPeye avatar Aug 28 '22 15:08 GPeye

Had the same issue,, I need to create IVector in rust in order to make it into ::windows::core::IntoParam<'a, IIterable<T>> form as it's required by windows crate api. I didn't find a single_threaded_vector or similar ones to use in rust. @kennykerr, I am relatively new to rust, curious how does below help if creating a collection isn't supported yet?

You can even just have a component that returns an empty collection that you can then populate using Rust.

tangp3 avatar Sep 02 '22 00:09 tangp3

Yes, there's been some progress here. You can now implement the collection interfaces in Rust. This issue remains open because I haven't yet published a stock implementation, such as cppwinrt's single_threaded_vector, that would simplify this considerably, but you can use the implement macro to define your own. The tests provide a few examples here:

https://github.com/microsoft/windows-rs/tree/master/crates/tests/implement/tests

kennykerr avatar Sep 02 '22 14:09 kennykerr

I am relatively new to rust, curious how does below help if creating a collection isn't supported yet?

You can even just have a component that returns an empty collection that you can then populate using Rust.

@tangp3 The core idea behind this revolves around the fact that the Windows Runtime provides a language-agnostic ABI. A Windows Runtime Components can be authored using any of the supported WinRT programming languages, and consumed from code written in any of the supported languages.

The workaround described takes advantage of this by creating a Windows Runtime Component using C++/WinRT that exposes a factory method (e.g. a static member of a runtimeclass) that returns an empty IVector. The implementation is as simple as returning a default-constructed single_threaded_vector, with all the implementation details well hidden behind the function template.

Rust code can now import this Windows Runtime Component and use its functionality to obtain an empty IVector whenever it needs one. With an IVector in hand, all methods and properties are instantly available to Rust (such as inserting, appending, or removing elements). What the workaround ultimately boils down to is enabling use of C++/WinRT's mature library code from Rust, with the Windows Runtime's ABI acting as mediator.

Authoring support for Windows Runtime Types in Rust has come a long way, and the implement macro makes much of this workaround moot. The exception being that there is no library code in the windows crate yet that provides an IVector implementation, so the burden of implementing the interface is still on the developer. That's pretty much what's behind this statement:

This issue remains open because I haven't yet published a stock implementation, such as cppwinrt's single_threaded_vector, that would simplify this considerably

tim-weis avatar Sep 13 '22 18:09 tim-weis

Any update on this I'm having some issues trying to pass input params that match these traits.

::windows::core::InParam<super::super::Foundation::Collections::IIterable<::windows::core::HSTRING>>

Using the example from https://github.com/microsoft/windows-rs/blob/master/crates/tests/implement/tests/into_impl.rs

I was able to get an instance of

Iterable<HSTRING>

But I'm too dumb to implement the into InParam trait.

reedHam avatar Feb 17 '23 03:02 reedHam

You should be able to pass a reference as follows:

let strings: IIterable<HSTRING> = ...
SomeMethod(&strings)?;

kennykerr avatar Feb 17 '23 18:02 kennykerr

I end up with a compiler error.

the trait `std::convert::From<&Iterable<windows::core::HSTRING>>` is not implemented for `&windows::Foundation::Collections::IIterable<windows::core::HSTRING>`

I'm trying to call these two functions.

  • https://microsoft.github.io/windows-docs-rs/doc/windows/Storage/FileProperties/struct.BasicProperties.html#method.RetrievePropertiesAsync
  • https://microsoft.github.io/windows-docs-rs/doc/windows/Storage/FileProperties/struct.BasicProperties.html#method.SavePropertiesAsync

Since I will have to implement IIterable<IKeyValuePair<HSTRING, IInspectable>> as well for the saving function this may just be too advanced for me.

Is there any ETA on the collections being completed?

reedHam avatar Feb 18 '23 01:02 reedHam

Not ETA, but I'm working on component authoring support at the moment and collection support is an important part of that.

kennykerr avatar Feb 19 '23 02:02 kennykerr

Good news, I was able to address some longstanding perquisites and started working on stock collections. For example, you will soon be able to write something like this:

let able = IIterable::<i32>::try_from(vec![1, 2, 3])?;

I should have these stock collections available soon.

kennykerr avatar Feb 23 '23 12:02 kennykerr

That was a busy week and concludes my work on WinRT collections for the time being. #2346, #2350, and #2353 cover the majority of cases where you'd need to create a collection to pass some data to an API. And these implementations are entirely thread safe!

I'll leave the implementation of mutable WinRT collections for the time being as that is far less important outside of component authors and even then, APIs should prefer immutable collections. If you need to implement IVector or IMap, just have a look at the stock implementations for inspiration.

Sorry it took so long, but that was a mountain of work! 🥲

kennykerr avatar Feb 24 '23 22:02 kennykerr