2015-02-02 2 views
12

У меня есть решение, содержащее C# и управляемые проекты на C++. Он компилируется в платформе решений x64 и x86. Поскольку он управляется C++, я хотел создать решение «Любой процессор» и избавиться от старых.Любой процессор недоступен в решении C++/C#

Я изменил настройки компоновщика проекта C++ на Force Safe IL Image для x64 и x86.

Далее, используя Configuration Manager, я создал новую платформу решений под названием «Любой процессор». Затем я добавил платформу проекта, также называемую «Any CPU».

Я продолжал устанавливать все проекты C# на «Любой процессор», но для C++ я не могу этого сделать. Платформа проекта «Любой процессор» не находится в раскрывающемся списке, а также нет опции «Создать ...».

В.С. это адепт об этом, поэтому я сохранил его, как было, и начал сборку. К моему удивлению, результатом DLL (из проекта C++) был MSIL, хотя платформа для C++ была x64. То же самое происходит при компиляции x32, результирующая DLL находится в MSIL.

Что дает? Почему я не могу настроить проект C++ на «Любой процессор»?

+2

возможно дубликат [Managed C++ и AnyCPU] (http://stackoverflow.com/questions/10413590/managed-c-and-anycpu) –

+1

Я не думаю, что это, потому что в результате DLL проекта C++ - это MSIL. Таким образом, нет необходимости делать «странные» вещи с загрузкой x64 или x86. Я просто не могу понять, почему я не могу скомпилировать Managed C++ как «Любой процессор» (в конфигурации) –

+1

Попытка объяснить, что конкретное имя платформы * полностью * не имеет значения при создании кода, который, как вы знаете, запускается на любой платформе - дело Геркулеса, которое никогда не было сделано. Единственное, что имеет значение, это переопределения джиттера в проекте EXE. –

ответ

10

Насколько я знаю, вы не можете создать тип проекта «AnyCPU» в Visual Studio для проекта C++/CLI. Тем не менее, вы можете сконфигурировать ваш проект C++/CLI (под типом проекта «Win32»), чтобы он составлял как чистый, безопасный MSIL без целевой платформы. Это позволит использовать вашу сборку C++/CLI DLL с проектом «AnyCPU» C#. То есть это эффективно «AnyCPU», хотя это не его фактическое имя в Configuration Manager.

В "C/C++" настройки проекта:

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

В настройках проекта "линкер":

  • CLR Тип изображения: просто убедитесь, что это не установлено явно IJW или PURE

Примечания:

  • Используя «безопасный» тип проекта, некоторые из опций компилятора и компоновщика, которые, как представляется, влияют на тип платформы будут игнорироваться. То есть вам не нужно проходить и устанавливать все на нестандартную платформу. Только выше. Но вы можете установить другие варианты на что-то подходящее, если вам станет лучше. :)
  • «Безопасный» предотвратит использование указателей. Если это важная проблема, то, по-видимому, можно сделать, хотя и с более сложным процессом. См. Creating a pure MSIL assembly from a C++/CLI project?.
  • Не забывайте, что по умолчанию Visual Studio создаст проекты C#, даже несмотря на то, что они являются «AnyCPU» и даже если они выполнены в 64-разрядной ОС, запустится как 32-разрядный процесс. Это может скрыть проблемы с рассогласованием платформы, если зависимость x86 вместо чистой/безопасной MSIL, как предполагалось. Просто что-то нужно знать (вы можете контролировать это, сняв флажок «Предпочитать 32-бит» на странице свойств проекта «Сборка» проекта C#).
+0

Этот ответ согласуется с тем, что я вижу в решении. Я не смог найти ссылки на, например, MSDN, которые объяснили, что пишет Питер, а именно: «вы не можете создать тип проекта AnyCPU в Visual Studio для проекта C++/CLI» –

+0

В VS2015 Update 5 это создает компилятор предупреждение D9035, в котором говорится о том, что мы действительно компилируем Managed C++, который является исчерпывающим, и поддержка будет удалена в будущей версии (еще не пробовал 2017 год, возможно, этот ответ больше недействителен). Позор, потому что это действительно то, что нам нужно, профиль компилятора/компоновщика AnyCPU. –

+0

Это недействительный ответ, потому что, если вы генерируете только MSIL, вы все равно не должны писать код на C++. Если вы пишете только программное обеспечение с использованием библиотек .NET Framework и MSIL, тогда вы просто затрудняетесь с тем, чтобы писать на C++. Единственное преимущество, которое я могу себе представить, это, пожалуй, с кодом PInvoke, но предупреждения и нестандартный/обесцениваемый подход отталкивают меня от этого решения. –

2

Для того, чтобы функциональность C++ использовалась dll C#, проект C++ должен создавать как x86, так и x64 версии dll. Невозможно ссылаться только на x86 или x64 dll из dll C#, скомпилированных с настройкой AnyCPU.

Уловка для получения DLL AnyCPU для работы с dll C++ во время выполнения удостоверяется, что сборка не может загрузить DLL C++, а затем подписаться на событие AppDomain AssemblyResolve. Когда сборка пытается загрузить DLL и терпит неудачу, ваш код имеет возможность определить, какая DLL должна быть загружена.

Подписавшись на событие выглядит примерно так:

System.AppDomain.CurrentDomain.AssemblyResolve += Resolver; 

обработчик событий выглядит примерно так:

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; 
} 

Я создал простой проект, демонстрирующий, как получить доступ к функциям C++ из библиотеки DLL AnyCPU ,

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

+1

Спасибо Тоби, я обновил свой ответ, надеюсь, он немного более информативен. –