Any CPU not available in C++/C# solution
Asked Answered
P

2

17

I have a solution that contains C# and managed C++ projects. It compiles in the solution platform x64 and x86. Since it is managed C++ I wanted to create a 'Any CPU' solution and get rid of the old ones.

I changed the C++ project linker settings to Force Safe IL Image for both x64 and x86.

Next, using the Configuration Manager, I created a new solution platform called 'Any CPU'. Next I added a project platform also called 'Any CPU'.

I proceeded to set all the C# projects to 'Any CPU', but for the C++ I can't do that. The project platform 'Any CPU' is not in the drop down, and there is also no option 'New...'.

VS is adement about it, so I kept it like it was and started a build. To my surprise the result DLL (from the C++ project) was MSIL even though the platform for C++ was x64. Same happens when compiling x32, the resulting DLL is in MSIL.

What gives? Why can't I set the C++ project to 'Any CPU'?

Peeve answered 2/2, 2015 at 14:36 Comment(4)
possible duplicate of Managed C++ and AnyCPUDevora
I don't think it is, because the resulting DLL from the C++ project is MSIL. So there is no need to do 'weird' stuff with loading x64 or x86. I just can't understand why I'm not able to compile Managed C++ as 'Any CPU' (in the configuration)Peeve
Trying to explain that the specific Platform name is completely irrelevant when you build code that, you know, runs on any platform is a Herculean job that's never done. The only thing that matters is the jitter overrides in the EXE project.Pascasia
@ChristopherPainter: this is not a duplicate of that post. The one you propose as a duplicate is discussing the use of platform-specific C++/CLI DLLs, selected automatically according to platform. Here, the OP wants a C++/CLI DLL assembly that has the same characteristic as a C# "AnyCPU" assembly. I.e. a single assembly which will can run on any platform.Locklear
L
17

As far as I know, you cannot create an "AnyCPU" project type in Visual Studio for a C++/CLI project. However, you can configure your C++/CLI project (under the "Win32" project type) so that it compiles as pure, safe MSIL, without a target platform. Doing so will allow your C++/CLI DLL assembly to be used with an "AnyCPU" C# project. I.e. it's effectively "AnyCPU", even though that's not its actual name in the Configuration Manager.

In the "C/C++" project settings:

  • Common Language RunTime Support: Safe MSIL Common Language RunTime Support (/clr:safe)

In the "Linker" project settings:

  • CLR Image Type: just make sure this isn't set explicitly to IJW or PURE

Notes:

  • By using the "safe" project type, a few of the compiler and linker options which appear to affect platform type will be ignored. I.e. you don't have to go through and set everything to a non-specific platform type. Just the above. But you may set the other options to something appropriate, if it makes you feel better. :)
  • "Safe" will prevent the use of pointers. If this is an important issue, it is apparently possible to do albeit with a more complicated process. See Creating a pure MSIL assembly from a C++/CLI project? for details.
  • Don't forget that by default, Visual Studio will create C# projects that even though they are "AnyCPU" and even though they are executed on a 64-bit OS, will start up as a 32-bit process. This can hide platform-mismatch issues, if a dependency is x86 instead of pure/safe MSIL as intended. Just something be aware of (you can control this by unchecking the "Prefer 32-bit" option in the C# project's "Build" project properties page).
Locklear answered 3/2, 2015 at 4:39 Comment(3)
This answer is consistent with what I see happening in the solution. I was not able to find any reference on for instance MSDN that explained what Peter is writing, namely "you cannot create an "AnyCPU" project type in Visual Studio for a C++/CLI project"Peeve
In VS2015 Update 5, this generates a compiler warning D9035 which tells us we are really compiling Managed C++ which is obslete and support will be removed in a future release (didn't try 2017 yet, maybe this answer is no longer valid). Shame because this is really what we want, an AnyCPU compiler/linker profile.Viyella
This is not a valid answer because if you are generating only MSIL then you shouldn't be writing code in C++ anyway. If you only write software using the .NET Framework and MSIL libraries then you are only making things difficult trying to write in C++. The only benefit I can imagine is perhaps with PInvoke code, but the warnings and non-standard/depreciated approach puts me off this solution.Viyella
F
6

In order for the C++ functionality to be consumed by a C# dll, the C++ project must produce both x86 and x64 versions of the dll. It is not possible to reference just a x86 or a x64 dll from a C# dll compiled with the AnyCPU setting.

The trick to getting the AnyCPU dll to play with the C++ dll, is at runtime make sure the assembly cannot load the C++ dll and then subscribe to the AppDomain AssemblyResolve event. When the assembly tries to load the dll and fails, then your code has the opportunity to determine which dll needs to be loaded.

Subscribing to the event looks something like this:

System.AppDomain.CurrentDomain.AssemblyResolve += Resolver;

Event handler looks something like this:

System.Reflection.Assembly Resolver(object sender, System.ResolveEventArgs args)
{
     string assembly_dll = new AssemblyName(args.Name).Name + ".dll";
     string assembly_directory = "Parent directory of the C++ dlls";

     Assembly assembly = null;
     if(Environment.Is64BitProcess)
     {
            assembly = Assembly.LoadFile(assembly_directory + @"\x64\" + assembly_dll);
     }
     else
     {
            assembly = Assembly.LoadFile(assembly_directory + @"\x86\" + assembly_dll);
     }
     return assembly;
}

I have created a simple project demonstrating how to access C++ functionality from an AnyCPU dll.

https://github.com/kevin-marshall/Managed.AnyCPU

Ferraro answered 22/11, 2016 at 17:32 Comment(1)
Thanks Toby, I have updated my answer, hopefully it is a little more informative.Ferraro

© 2022 - 2024 — McMap. All rights reserved.