Yort Yort - 4 months ago 16
C Question

Referencing C Dlls from Windows 10 Universal App Across CPU Architectures

Basic question/summary: I need to reference a binary (dll) created by someone else in C from a Win 10 universal app project. However, there is a separate dll for x86 and arm. I believe I need to reference the dll (or at least winmd file) from the project for it to be deployed, but I can only reference one file not both. That means the app fails on one platform or another (desktop or phone) because it has the wrong binary included. Looking for a solution.

More detailed explanation;

I am trying to write a Universal Windows application (new Windows 10 style). This means I have a single project to add references to external components to.

I have the need for some image processing stuff that is best bought as a 3rd party component rather than developed in house. There are several SDK's available from 3rd parties that support WinRT but none that specifically support UWA. The WinRT SDK's however all have different binaries for Windows Phone and Windows Desktop apps. and the binaries are all created from C/C++ source. This was fine with the older 'universal' apps because there was a separate project for phone and desktop so you could just reference different components in each project, but now there's only one project to add references to.

I asked one supplier about UWA support and they claimed it was impossible, they couldn't create a single binary to target both platforms (arm vs x86) and they didn't know a way for my UWA to reference the right file when the app is built for the appropriate architecture (which is what I assume should happen).

I assume there is someway (perhaps in a winmd file?) to say, 'hey, here's two copies of the same dll for different CPU architectures, pick the one you're building for' and so long as the public API matches the app just uses the right one?

Is there a solution for this? Does anyone know how this sort of reference is supposed to work? Or am I just out of luck?

Thanks.

Answer

There is a way to reference the same DLL with different architectures in a project but you cannot do it from VS directly. You will have to manually edit the csproj file.

In your csproj file, you will have to go to the bottom and locate the sections. These sections reference all your files.

There is a special tag in the project definition which allows you to tell Visual Studio to perform some specific actions based on some conditions. You can then create a group which will reference your DLL dependencies. Your csproj file will then be as the following: (I've removed all the non-relevants things)

<Project>
  <PropertyGroup />
  <PropertyGroup />
  <PropertyGroup />
  <ItemGroup />
  <ItemGroup />
  <Choose>
    <When Condition=" '$(Platform)' == 'x86' ">
      <ItemGroup>
        <Content Include="..\Binaries\x86\MyLib1.winmd">
            <CopyToOutputDirectory>Always</CopyToOutputDirectory>
        </Content>
         <Content Include="..\Binaries\x86\MyLib2.winmd">
          <CopyToOutputDirectory>Always</CopyToOutputDirectory>
        </Content>
      </ItemGroup>
    </When>
    <When Condition=" '$(Platform)' == 'ARM' ">
      <ItemGroup>
        <Content Include="..\Binaries\ARM\MyLib1.winmd">
            <CopyToOutputDirectory>Always</CopyToOutputDirectory>
        </Content>
         <Content Include="..\Binaries\ARM\MyLib2.winmd">
          <CopyToOutputDirectory>Always</CopyToOutputDirectory>
        </Content>
      </ItemGroup>
    </When>
  </Choose>
  <Import />
  <Import />
</Project>

I've used it on VS2013 for some Windows Phone projects (to make them work both on the phone and the emulator). I've not tested on Windows 10 and VS2015 but it should work the same way.