I created a C++ project in Visual Studio Class library CLR (.NET Framework)
:
#pragma once
using namespace System;
#ifdef _M_X64
namespace MyDLL64 {
#else
namespace MyDLL32 {
#endif
public ref class MyClass
{
public: static String^ Foo(String^ arg)
{
String^ str = arg->ToUpper();
return str;
}
};
}
Then I compiled two libraries(x86 and x64). Thereafter I add them to references in my C# project
and added their methods to the code:
String res = "";
if (IntPtr.Size == 8)
{
res = MyDLL64.MyClass.Foo("test string");
}
else
{
res = MyDLL32.MyClass.Foo("test string");
}
Console.WriteLine(res);
But I am getting this error:
System.BadImageFormatException: "Could not load file or assembly 'MyDLL64, Version=1.0.8197.24341, Culture=neutral, PublicKeyToken=null', or one of their dependencies. An attempt was made to load a program with an invalid format."
(or MyDLL32...
if arch is 64 bit).
By the way, this code starts correctly without exceptions:
String res = "";
if (IntPtr.Size == 8)
{
res = MyDLL64.MyClass.Foo("test string");
}
if (1 > 2)
{
res = MyDLL32.MyClass.Foo("test string");
}
Console.WriteLine(res);
So how properly add x32 and x64 C++CLR dlls to my Any CPU C# DLL?
So how properly add x32 and x64 C++CLR dlls to my Any CPU C# DLL?
You can't. AnyCPU just means that the self process can be executed either as a 32 or 64 bit one depending on the architecture but once a 64 bit process is spawned it cannot access 32 bit images and vice versa.
If your C# project references native images, then instead of building one AnyCPU image you must create two separate images just like in case of the C++ project.
Specify x86 and x84 targets for the solution. And then if your 32/64-bit C++ dlls are named differently, then you can edit your .csproj file like this:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
</PropertyGroup>
<PropertyGroup Condition="'$(Platform)'=='x86'">
<PlatformTarget>x86</PlatformTarget>
<DefineConstants>$(DefineConstants);X86</DefineConstants>
</PropertyGroup>
<ItemGroup Condition="'$(Platform)'=='x86'">
<Reference Include="MyDLL32"/>
</ItemGroup>
<PropertyGroup Condition="'$(Platform)'=='x64'">
<PlatformTarget>x64</PlatformTarget>
<DefineConstants>$(DefineConstants);X64</DefineConstants>
</PropertyGroup>
<ItemGroup Condition="'$(Platform)'=='x64'">
<Reference Include="MyDLL64"/>
</ItemGroup>
</Project>
And then the C# code can have similar #if
directives than the C++ one:
String res = "";
#if X64
res = MyDLL64.MyClass.Foo("test string");
#else
res = MyDLL32.MyClass.Foo("test string");
#endif
Console.WriteLine(res);
But IMHO it would be nicer if the C++ images used the same namespaces so the C# code does not need the #if
directives and the different images could be handled purely in the .csproj file (in which case you don't need the DefineConstants
either).