У меня есть решение, которое содержит 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 ++ значение «Любой процессор»?
Насколько я знаю, вы не можете создать тип проекта AnyCPU в Visual Studio для проекта C ++ / CLI. Тем не менее, вы Можно настройте свой проект C ++ / CLI (в соответствии с типом проекта «Win32»), чтобы он компилировался как чистый, безопасный MSIL без целевой платформы. Это позволит использовать вашу C ++ / CLI DLL-сборку с проектом AnyCPU C #. То есть это фактически «AnyCPU», даже если это не настоящее имя в Configuration Manager.
В настройках проекта «C / C ++»:
Safe MSIL Common Language RunTime Support (/clr:safe)
В настройках проекта «Линкер»:
IJW
или же PURE
Заметки:
Для того чтобы функциональность 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.