Любой процессор недоступен в решении С++/С#
У меня есть решение, которое содержит С# и управляемые проекты на С++.
Он компилируется на платформе решений x64 и x86. Поскольку он управляется С++, я хотел создать решение "Любой процессор" и избавиться от старых.
Я изменил настройки компоновщика проектов на С++ в Force Safe IL Image для x64 и x86.
Затем, используя Configuration Manager, я создал новую платформу решений под названием "Any CPU". Затем я добавил платформу проекта, также называемую "Any CPU".
Я продолжал устанавливать все проекты С# на "Любой процессор", но для С++ я не могу этого сделать. Платформа проекта "Любой процессор" не находится в раскрывающемся списке, а также нет опции "Создать...".
VS - это об этом, поэтому я сохранил его, как было, и начал сборку. К моему удивлению, результатом DLL (из проекта С++) был MSIL, хотя платформа для С++ была x64. То же самое происходит при компиляции x32, результирующая DLL находится в MSIL.
Что дает?
Почему я не могу установить проект С++ на "Любой процессор"?
Ответы
Ответ 1
Насколько я знаю, вы не можете создать тип проекта "AnyCPU" в Visual Studio для проекта С++/CLI. Однако вы можете сконфигурировать свой проект С++/CLI (под типом проекта "Win32" ), чтобы он компилировался как чистый, безопасный MSIL без целевой платформы. Это позволит использовать вашу сборку С++/CLI DLL с проектом "AnyCPU" С#. То есть это эффективно "AnyCPU", хотя это не его фактическое имя в Configuration Manager.
В настройках проекта "C/С++":
- Поддержка RunTime Common Language:
Safe MSIL Common Language RunTime Support (/clr:safe)
В настройках проекта "Linker":
- Тип изображения CLR: просто убедитесь, что это явно не указано
IJW
или PURE
Примечания:
- Используя "безопасный" тип проекта, некоторые из параметров компилятора и компоновщика, которые, как представляется, влияют на тип платформы, будут игнорироваться. То есть вам не нужно проходить и устанавливать все на нестандартный тип платформы. Только выше. Но вы можете установить другие варианты на что-то подходящее, если вам станет лучше.:)
- "Безопасный" предотвратит использование указателей. Если это важная проблема, то, по-видимому, можно сделать, хотя и с более сложным процессом. Подробнее см. Создание чистой сборки MSIL из проекта С++/CLI.
- Не забывайте, что по умолчанию Visual Studio создаст проекты С#, даже несмотря на то, что они являются "AnyCPU" и даже если они выполнены в 64-разрядной ОС, запустится как 32-разрядный процесс. Это может скрыть проблемы с рассогласованием платформы, если зависимость x86 вместо чистой/безопасной MSIL, как предполагалось. Просто что-то нужно знать (вы можете это контролировать, сняв флажок "Предпочитать 32-разрядную" на странице свойств проекта "Создать" на странице С#.)
Ответ 2
Для того, чтобы функциональность С++ потреблялась dll С#, проект С++ должен создавать версии dll x86 и x64. Невозможно ссылаться только на x86 или x64 dll из dll С#, скомпилированных с настройкой AnyCPU.
Трюк для получения DLL AnyCPU для работы с dll С++ во время выполнения удостоверяется, что сборка не может загрузить DLL С++, а затем подписаться на событие 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;
}
Я создал простой проект, демонстрирующий, как получить доступ к функциям С++ из DLL AnyCPU.
https://github.com/kevin-marshall/Managed.AnyCPU