简体   繁体   中英

Consuming C++/WinRT Components from C#

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?

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:

  1. Define your component's API in an IDL file
  2. Invoke MIDL to compile the IDL into metadata (.winmd)
  3. Invoke the cppwinrt.exe compiler to generate the scaffolding to implement your runtimeclass(es) along with the DllGetActivationFactory hooks needed for activation.

Want details of what's happening?

Step 1: IDL

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;
  }
}

Step 2: Create winmd

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:

  • Enable Windows Runtime (adds /winrt)
  • Add your metadata reference directory. If you were targeting the 16299 SDK, this would be $(FrameworkSdkDir)References\\10.0.16299.0\\Windows.Foundation.FoundationContract\\3.0.0.0 . Update appropriately if you're targeting a different SDK.
  • Set your output metadata file. It's usually simplest to set this to $(ProjectName).winmd
  • Add /nomidl and /struct_by_ref to your MIDL command line. Just trust me.

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.

Step 3:

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM