AnyCPU/x86/x64 для приложения С# и его зависимость от С++/CLI
Я разработчик Windows, я использую Microsoft visual studio 2008 SP1. Моя машина для разработчиков - 64 бит.
В настоящее время я работаю над программным обеспечением, написанным на С#.exe. К сожалению, я не смог решить всю проблему исключительно на С#. Вот почему я также разработал небольшую управляемую DLL в С++/CLI. Оба проекта находятся в одном и том же решении.
My С#.exe build target - "Любой процессор". Когда моя цель сборки С++ DLL - "x86", DLL не загружается.
Насколько я понял, когда я googled, причина в том, что язык С++/CLI, в отличие от других языков .NET, компилируется в собственный код, а не управляется кодом.
Я переключил цель сборки С++ DLL на x64, и теперь все работает. Тем не менее, AFAIK все перестанет работать, как только мой клиент установит мой продукт на 32-разрядную ОС. Я должен поддерживать Windows Vista и 7, как 32, так и 64-разрядные версии каждого из них.
Я не хочу возвращаться к 32 битам. Это 250 строк кода на С++ в моей DLL составляет всего 2% от моей кодовой базы. И эта DLL используется только в нескольких местах, поэтому в типичном сценарии использования она даже не загружена.
Моя DLL реализует два COM-объекта с ATL, поэтому я не могу использовать параметр /clr: safe.
Есть ли способ настроить решение и проекты, чтобы проект С# создавал версию "Любой процессор", проект С++ создает и 32-битную и 64-битную версии, а затем во время выполнения, когда управляемый .EXE запускается, он использует 32-разрядную DLL или 64-разрядную DLL в зависимости от ОС?
Или может быть какое-то лучшее решение, о котором я не знаю?
Спасибо заранее!
Ответы
Ответ 1
С ним нет простого способа. Если у вас есть собственный код (т.е. Ваш С++), и вам нужно поддерживать x86, тогда вам нужно скомпилировать x86 (если вы не хотите работать в мире WOW... т.е. запустить 32-разрядный код как в 32, так и в 64-битных средах). Вы можете иметь как x86, так и x64 дистрибутивы, но если вы поддерживаете 32 и 64 бит, и у вас есть собственный код или COM introp ', то вы должны иметь как 32, так и 64-битные двоичные файлы. "Любой процессор" действительно полезен только тогда, когда нет собственного кода или интерполя, тогда вы получаете этот benifit.
Ответ 2
Существует способ: иметь оболочку С# AnyCPU и проект С++ для каждой архитектуры, а также позволить оболочке С# загружать правильный проект С++ во время выполнения.
Для проекта С++ создайте одну версию для каждой архитектуры (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... */
}
}
И в коде С++ я использую те же источники, что и я, но буду компилировать их в другое пространство имен в зависимости от архитектуры сборки:
#ifdef _M_X64
namespace Cpp64 {
#else
namespace Cpp32 {
#endif
public ref class MyCPlusPlusClass
{
public: static __int64 Method(void) { return 123; }
};
}