AnyCPU / x86 / x64 для приложения на C # и его зависимость от C ++ / CLI - PullRequest
17 голосов
/ 03 июня 2010

Я разработчик для Windows, я использую Microsoft Visual Studio 2008 SP1. Моя машина разработчика 64-битная.

Программное обеспечение, над которым я сейчас работаю, - это .exe, написанный на C #. К сожалению, мне не удалось решить всю проблему исключительно в C #. Вот почему я также разработал небольшую управляемую DLL на C ++ / CLI. Оба проекта находятся в одном решении.

Моя цель сборки C # .exe - «Любой процессор». Когда моя цель сборки DLL C ++ - "x86", DLL не загружается. Насколько я понял, когда я гуглял, причина в том, что язык C ++ / CLI, в отличие от других языков .NET, компилируется в нативный код, а не в управляемый код.

Я переключил цель сборки DLL C ++ на x64, и теперь все работает. Тем не менее, AFAIK все перестанет работать, как только мой клиент установит мой продукт на 32-битной ОС. Я должен поддерживать Windows Vista и 7, 32- и 64-разрядные версии каждой из них.

Я не хочу отступать от 32 бит. Эти 250 строк кода C ++ в моей DLL составляют только 2% моей кодовой базы. И эта DLL используется только в нескольких местах, поэтому в типичном сценарии использования она даже не загружается.

Моя DLL реализует два COM-объекта с ATL, поэтому я не могу использовать настройку проекта " / clr: safe ".

Есть ли способ настроить решение и проекты таким образом, чтобы проект C # создавал версию «Любой ЦП», проект C ++ собирал как 32-разрядную, так и 64-разрядную версии, а затем во время выполнения при управлении. EXE запускается, использует 32-битную или 64-битную DLL в зависимости от ОС?

Или, может быть, есть лучшее решение, о котором я не знаю?

Заранее спасибо!

Ответы [ 2 ]

10 голосов
/ 22 июня 2012

Существует способ: иметь оболочку «AnyCPU» C # и проект C ++ для каждой архитектуры и позволить оболочке C # загружать нужный проект C ++ во время выполнения.

Для проекта C ++ создайте одну версию для каждой архитектуры (x86, x64) и соберите их все. Затем в обертке сделать:

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... */
    }
}

И в коде C ++ я использую те же источники, что и сказал, но скомпилирую в другое пространство имен в зависимости от архитектуры build :

#ifdef _M_X64
namespace Cpp64 {
#else
namespace Cpp32 {
#endif
    public ref class MyCPlusPlusClass
    {
        public: static __int64 Method(void) { return 123; }
    };
}
7 голосов
/ 03 июня 2010

Легкого пути нет. Если у вас есть собственный код (т. Е. Ваш C ++) и вам нужно поддерживать x86, то вам нужно скомпилировать x86 (если вы не хотите работать в мире WOW ... т.е. запускать 32-битный код как в 32-, так и в 64-битной среде). Вы можете иметь как x86, так и x64 дистрибутивы, но если вы поддерживаете как 32, так и 64-битную версию, и у вас есть собственный код или COM introp ', то вам нужно иметь оба 32 и 64-битные двоичные файлы. «Любой процессор» действительно полезен только тогда, когда нет нативного кода или взаимодействия, тогда вы получаете это преимущество.

...