Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AnyCPU/x86/x64 for C# application and it's C++/CLI dependency

I'm Windows developer, I'm using Microsoft visual studio 2008 SP1. My developer machine is 64 bit.

The software I'm currently working on is managed .exe written in C#. Unfortunately, I was unable to solve the whole problem solely in C#. That's why I also developed a small managed DLL in C++/CLI. Both projects are in the same solution.

My C# .exe build target is "Any CPU". When my C++ DLL build target is "x86", the DLL is not loaded. As far as I understood when I googled, the reason is C++/CLI language, unlike other .NET languages, compiles to the native code, not managed code.

I switched the C++ DLL build target to x64, and everything works now. However, AFAIK everything will stop working as soon as my client will install my product on a 32-bit OS. I have to support Windows Vista and 7, both 32 and 64 bit versions of each of them.

I don't want to fall back to 32 bits. That 250 lines of C++ code in my DLL is only 2% of my codebase. And that DLL is only used in several places, so in the typical usage scenario it's not even loaded.

My DLL implements two COM objects with ATL, so I can't use "/clr:safe" project setting.

Is there way to configure the solution and the projects so that C# project builds "Any CPU" version, the C++ project builds both 32 bit and 64 bit versions, then in the runtime when the managed .EXE is starting up, it uses either 32-bit DLL or 64-bit DLL depending on the OS?

Or maybe there's some better solution I'm not aware of?

Thanks in advance!

like image 958
Soonts Avatar asked Jun 03 '10 06:06

Soonts


People also ask

What does Anycpu mean?

The default setting, "Any CPU", means that the assembly will run natively on the CPU it is currently running on. Meaning, it will run as 64-bit on a 64-bit machine and 32-bit on a 32-bit machine. If the assembly is called from a 64-bit application, it will perform as a 64-bit assembly and so on.

Should I install Visual Studio x86 or x64?

In most cases you should install both the x64 (64-bit) and the x86 (32-bit) versions. If you're using a 32-bit version of Windows, then you only need to install the x86 version.

What does x86 mean in Visual Studio?

It usually refers to x86 for 32 bit OS and x64 for system with 64 bit. Technically x86 simply refers to a family of processors and the instruction set they all use.

What is the difference between x86 and x64 in Visual Studio?

The x86 libraries are for 32-bit applications, and the x64 libraries are for 64-bit applications. You can see which platform you are targetting in Visual Studio's Configuration Manager.


2 Answers

There is a way: to have an "AnyCPU" C# wrapper and a C++ project per architecture, and let the C# wrapper load the right C++ project at run time.

For the C++ project, create one version per different architecture (x86, x64), and build them all. Then in the wrapper do:

public class CppWrapper
{
    // C++ calls that will be dynamically loaded from proper architecture:
    public static readonly Func<long> MyCplusplusMethodUsableFromCsharpSpace;

    // Initialization:
    static CppWrapper()
    {
        if(Environment.Is64BitProcess)
        {
            MyCplusplusMethodUsableFromCsharpSpace = CppReferences64.MyCplusplusClass.Method;
            // Add your 64-bits entry points here...
        }
        else
        {
            MyCplusplusMethodUsableFromCsharpSpace = CppReferences32.MyCplusplusClass.Method;
            /* Initialize new 32-bits references here... */
        }
    }

    // Following classes trigger dynamic loading of the referenced C++ code
    private static class CppReferences64
    {
        public static readonly Func<long> MyCplusplusMethod = Cpp64.MyCplusplusMethod;
        /* Add any64-bits references here... */
    }
    private static class CppReferences32
    {
        public static readonly Func<long> MyCplusplusMethod = Cpp32.MyCplusplusMethod;
        /* Add any 32-bits references here... */
    }
}

And in the C++ code, I use the same sources as I said, but will compile to different namespace depending on the build architecture:

#ifdef _M_X64
namespace Cpp64 {
#else
namespace Cpp32 {
#endif
    public ref class MyCPlusPlusClass
    {
        public: static __int64 Method(void) { return 123; }
    };
}
like image 170
gatopeich Avatar answered Oct 18 '22 01:10

gatopeich


There is no easy way around it. If you have native code (i.e. your C++) and you need to support x86, then you have to compile x86 (unless you want to work in WOW world...ie. running 32 bit code in both 32 and 64 bit envrionments). You can have both an x86 and x64 distributions, but if you're supporting both 32 and 64 bit, and you have native code or COM introp' then you have to have both 32 and 64 bit binaries. "Any CPU" only really is useful when there is no native code or interop, then you get that benifit.

like image 42
David B Heise Avatar answered Oct 18 '22 01:10

David B Heise