Here's my problem. I am wrapping a C dll in C#. To do this, I am first writing a C++/CLI wrapper. The native C library is linked to the C++/CLI wrapper. (Linker properties in C++/cli project).
Here's how it is all organised now: - The native C .lib: both x86 and 64bit.
My problem comes from the fact that I need C# to target "Any CPU". But this option is not available in C++/CLI since it compiles directly to native code.
My idea to solve this is: - Compile C++/CLI wrapper in x86 and then change the config and compile to 64 bit. When it compiles, I would like to tell it which dll to take based on the platform. ie: if compiling in 64bit, link 64 bit native C dll, else if x86, link x86 native C. - With this done, I should then be able to have Any CPU target in my C# platform. Here again, instead of referencing my C++/CLI wrapper project, I would reference the required dll based on the target platform.
My questions are:
Let me add that the C# project a CLASS LIBRARY to be used by an x86 or x64 client.
I hope my question is clear enough. Any helps would be appreciated !
UPDATE based on:Conditional references in .NET project, possible to get rid of warning?...
So now I've edited my .csproj file using a condition to reference the dll as follows:
<ItemGroup>
    <Reference Include="AlibCppWrapper, Version=1.0.4303.21410, Culture=neutral, PublicKeyToken=c0c17a53adc44091, processorArchitecture=AMD64"
               Condition="$(Platform) == 'x64'">
      <SpecificVersion>False</SpecificVersion>
      <HintPath>..\x64\Debug\AlibCppWrapper.dll</HintPath>
    </Reference>
    <Reference Include="AlibCppWrapper, Version=1.0.4303.21410, Culture=neutral, PublicKeyToken=c0c17a53adc44091, processorArchitecture=x86"
               Condition="$(Platform) == 'x86'">
      <SpecificVersion>False</SpecificVersion>
      <HintPath>..\Debug\AlibCppWrapper.dll</HintPath>
    </Reference>
  </ItemGroup>
Unfortunately this doesn't work as the $(Platform) is set to AnyCPU...
What you describe is known as "side-by-side assembly" (two versions of the same assembly, one 32 and the other 64 bit)... I think you will find these helpful:
EDIT - as per comment:
Here you can find a walkthrough for exactly your scenario: .NET DLL wrapping C++/CLI DLL referencing a native DLL
For me solution was following:
Build x64 bit version of C++ library to output file xxx.x64.dll
Build x86 bit (Win32 platform) version of C++ library to output file xxx.x86.dll
Add them as content files to my wrapper C# project. Ex.:
<ItemGroup>
  <Content Include="..\..\$(Configuration)\xxx.x86.dll" Link="xxx.x86.dll">
    <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
  </Content>
  <Content Include="..\..\$(Configuration)\xxx.x64.dll" Link="xxx.x64.dll">
    <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
  </Content>
</ItemGroup>
In C# Import functions from both x86 and x64 library versions. Ex.:
    [DllImport("xxx.x86.dll", EntryPoint = "FunctionName", SetLastError = true, CharSet = CharSet.Unicode, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
    public static extern void FunctionNamex86();
    [DllImport("xxx.x64.dll", EntryPoint = "FunctionName", SetLastError = true, CharSet = CharSet.Unicode, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
    public static extern void FunctionNamex64();
In C# implement function that calls correct overload based on current platform. Ex.:
    public static void FunctionName()
    {
        if (Environment.Is64BitProcess)
            FunctionNamex64();
        else
            FunctionNamex86();
    }
Now C# project can be built as "Any CPU" and used by other multiplatform projects.
To distribute it as NuGet package, I use following NuSpec configuration:
<?xml version="1.0"?>
<package>
    <metadata>
        <contentFiles>
            <files include="any/any/xxx.x64.dll" buildAction="None" copyToOutput="true" />
            <files include="any/any/xxx.x86.dll" buildAction="None" copyToOutput="true" />
        </contentFiles>
    </metadata>
    <files>
        <file src="Release/C#Wrapper.dll" target="lib" /> 
        <file src="Release/xxx.x64.dll" target="content" /> 
        <file src="Release/xxx.x86.dll" target="content" /> 
        <file src="Release/xxx.x64.dll" target="contentFiles/any/any" /> 
        <file src="Release/xxx.x86.dll" target="contentFiles/any/any" /> 
    </files>
</package>
Answer is mostly based on: Using a 32bit or 64bit dll in C# DllImport
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With