Reputation: 309
I have a project (dynamic library) written in C++/CX, this project is consumed by a Windows 10 Universal App written in C# (targeting x86 and ARM32).
I want to rewrite the library to C++/WinRT in order to use vanilla C++.
Q1: Is it possible to create a C++/WinRT DLL and consume it from C#?
Q2: How do I set up the C++/WinRT project to enable it to be consumed from the store app?
Upvotes: 5
Views: 2335
Reputation: 815
The cppwinrt.exe compiler started shipping in the Windows Preview SDK November-ish 2017. With it, you can more easily create your own C++/WinRT component so that it can be consumed by other store apps.
There's a sample on github (https://github.com/kennykerr/cppwinrt/tree/master/Store/Component) that does just this for a C++ store app. Obviously, the App project would need to be different for a C# app, but this should be enough to get you started. In particular, the C++/WinRT component project, though basic, contains most of the magic sauce you'd need to create your component.
We're actively working on making this experience even more seamlesss with project templates and other goodies, but for now, you can still do this in a way similar to the linked sample without too much work.
The short version of what's happening in the sample is:
Want details of what's happening?
The sample's API is pretty simple, so I'll just post it here.
import "Windows.Foundation.idl";
namespace Component
{
runtimeclass Button;
[version(1.0), uuid(461c8806-8bc2-4622-8eac-b547c39f867e), exclusiveto(Button)]
interface IButton : IInspectable
{
[propget] HRESULT Text([out,retval] HSTRING* value);
};
[version(2.0), uuid(d3235252-4081-4cc8-b0e0-8c7691813845), exclusiveto(Button)]
interface IButton2 : IInspectable
{
HRESULT Show();
};
[version(1.0), activatable(1.0)]
runtimeclass Button
{
[default] interface IButton;
interface IButton2;
interface Windows.Foundation.IStringable;
}
}
This just requires that you pass the correct command line arguments to MIDL, which can be seen in Visual Studio for the project properties and the properties of your IDL file. What you need are:
$(FrameworkSdkDir)References\10.0.16299.0\Windows.Foundation.FoundationContract\3.0.0.0
. Update appropriately if you're targeting a different SDK.$(ProjectName).winmd
At this point, building the project should now generate a winmd file. In the linked sample, it will be name Component.winmd. If you want, you can use ildasm to crack open the winmd and verify it's got all your stuff in it.
Run cppwinrt.exe to generate the scaffolding. You can see in the Component project that it has a CustomBuildStep that calls cppwinrt.exe with some arguments: cppwinrt.exe -in $(ProjectDir)Component.winmd -comp $(ProjectDir) -out "$(ProjectDir)Generated Files" -ref 10.0.17061.0 -verbose
-in
The input winmd location. This is what you generated in step 2.-comp
We're running in "component" mode, so that it generates the scaffolding.-out
Where to put the generated scaffolding.-ref
Where to find the input winmd(s) that your winmd depends on. You can also specify an SDK version (which is what's happening here) or -ref local
to simply use whatever is on your running OS. Using the SDK version is cleanest.-verbose
Self-explanatory.Download the sample project and play with a bit. From there, it should hopefully be straightforward to set up your own component and app.
Upvotes: 6