Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Interop with c++/cx #40

Closed
beark opened this issue May 17, 2017 · 3 comments
Closed

Interop with c++/cx #40

beark opened this issue May 17, 2017 · 3 comments

Comments

@beark
Copy link

beark commented May 17, 2017

I was wondering if there's some good way of calling into rust code I've written with winrt-rust from, eg, a XAML control I wrote in C++?

Trivial interop I've already managed, but I'd like to be able to write, say, an IAsyncAction in rust that I can call from C++, and this has so far proved difficult.

Specifically, I wrote the following fairly trivial thing in Rust and compiled as a static library:

#[no_mangle]
pub extern fn test() -> HString {
    HString::new("Hello from rust!")
}

#[no_mangle]
pub extern fn do_async_stuff() -> ComPtr<IAsyncOperation<StorageFile>> {
    let uri = Uri::create_uri(FastHString::new("ms-appx:///Assets/file.txt").deref()).unwrap();
    StorageFile::get_file_from_application_uri_async(&uri).unwrap()
}

And in my C++ control I have

extern "C" {
    extern HSTRING test();
    extern WhatGoesHere? do_async_stuff();
}

MainPage::MainPage()
{
    InitializeComponent();
    this->TXT->Text = ref new String(test());
}

I' don't think it's possible to express the type needed in C terms, so I suppose I would have to get around that by using, say, a void pointer and re-interpret cast it. But to what? I assume the hat pointer types are not what's used on the Rust side...

@Boddlnagg
Copy link
Collaborator

This is an interesting use case that I haven't thought about before (actually, I haven't thought much about use cases of winrt-rust at all 😄 ).

Unfortunately I don't know much about C++/CX, so I'm not sure how the hat pointers (^) there look at the ABI level. This documentation suggests that they are ABI compatible with raw pointers, so it might be possible to just write ^IAsyncOperation<StorageFile> on the C++/CX side where you have ComPtr<IAsyncOperation<StorageFile>> (both are just *IAsyncOperation<StorageFile> with additional "magic"). So maybe this works out of the box?

You might also be able to use the new C++/WinRT projection (https://github.com/Microsoft/cppwinrt) instead of C++/CX, but this depends on what you want to do from the C++ side. GUI development is probably hard with C++/WinRT because there is no GUI designer yet as far as I know.

@beark
Copy link
Author

beark commented May 17, 2017

Interesting, it seems it does indeed work to just cast directly to the expected C++/CX types. It's a bit ugly, since the rust functions need to be declared in "C" on the C++-side, but it works. For reference, I now have:

Static rust lib

#[no_mangle]
pub extern fn do_async_stuff() -> ComPtr<IAsyncOperation<StorageFile>> {
    let uri = Uri::create_uri(FastHString::new("ms-appx:///Assets/file.txt").deref()).unwrap();
    StorageFile::get_file_from_application_uri_async(&uri).unwrap()
}

C++ "Universal application"

extern "C" {
    extern void* do_async_stuff();
}

MainPage::MainPage()
{
    InitializeComponent();

    auto temp = do_async_stuff();
    auto storageFileTask = reinterpret_cast<IAsyncOperation<Windows::Storage::StorageFile^>^>(temp);

    auto t = concurrency::create_task(storageFileTask);
    t.then([this](Windows::Storage::StorageFile^ file) {
        TXT->Text = file->FileType;
    });
}

And the XAML-defined TextBlock named TXT gets populated by the .filetype of the asset. Pretty cool.

@Boddlnagg
Copy link
Collaborator

I'm closing this, since it seems solved.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants