Любой процессор недоступен в решении C ++ / C #

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

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

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

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

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

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

14

Решение

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

В настройках проекта «C / C ++»:

  • Поддержка общего языка RunTime: Safe MSIL Common Language RunTime Support (/clr:safe)

В настройках проекта «Линкер»:

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

Заметки:

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

Другие решения

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

Хитрость в том, чтобы заставить AnyCPU dll играть с 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 ++ из библиотеки AnyCPU.

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

2

По вопросам рекламы [email protected]