Any CPU dependent on C++/CLI dependent on native C dll (any cpu for c++/cli)

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:

  • Using Side-by-Side assemblies to load the x64 or x32 version of a DLL
  • http://blogs.msdn.com/b/gauravseth/archive/2006/03/07/545104.aspx
  • http://www.thescarms.com/dotnet/Assembly.aspx

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:

  1. Build x64 bit version of C++ library to output file xxx.x64.dll

  2. Build x86 bit (Win32 platform) version of C++ library to output file xxx.x86.dll

  3. 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>
    
  4. 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();
    
  5. In C# implement function that calls correct overload based on current platform. Ex.:

        public static void FunctionName()
        {
            if (Environment.Is64BitProcess)
                FunctionNamex64();
            else
                FunctionNamex86();
        }
    
  6. Now C# project can be built as "Any CPU" and used by other multiplatform projects.

  7. 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