Вы можете создать AnyCPU dll с C ++ / CLI , но в простейшем случае вы не сможете использовать MFC, ATL или CRT.Однако, если вы просто хотите написать чистый управляемый код .NET на C ++ / CLI, включая управляемые указатели (что не разрешено /clr:safe
), и получить более сложную оптимизацию кода компилятора C ++ / CLI, читайте дальше:
- Для достижения наилучших результатов начните с нового проекта из шаблона проекта библиотеки управляемых классов.Установите свойства проекта C ++ / CLI для библиотеки классов DLL на
/clr:pure
.Это на странице Configuration Properties
в Visual Studio 2010. - На панели C / C ++ установите
Omit Default Library Name
на Yes /Zl
- Для компоновщика отключите
Incremental Linking
и Link Library Dependencies
- На странице «Дополнительно» компоновщика я установил для целевой машины значение
Not Set
, а для типа изображения CLR - Force Pure IL Image /CLRIMAGETYPE:PURE
, но некоторые из этих видимых настроек не учитываются, поскольку флаг 32BIT +все еще устанавливается компоновщиком в заголовке PE32. - Поэтому добавьте шаг
corflags
в вашу сборку.Лучший способ сделать это - выйти из Visual Studio и отредактировать файл vcxproj в текстовом редакторе.Внизу файла добавьте:
<!-- at the bottom of the file... -->
<Target Name="AfterBuild">
<Exec Command="corflags $(TargetPath) /32BIT-" />
</Target>
</Project>
Запустится инструмент corflags
, чтобы отключить флаг 32BIT в вашей DLL.Убедитесь, что в вашем пути доступен инструмент corflags.exe
. - Наконец, добавьте запись-заглушку в исходный файл C ++ / CLI.Это статический конструктор модуля.Для меня сработало размещение следующего вне пространства имен:
#pragma warning(disable:4483)
void __clrcall __identifier(".cctor")() { }
Вот и все, теперь вы можете построить AnyCPU dll;это чисто MSIL
благодаря «чистым» настройкам, и он будет загружаться как x64 или x86 благодаря настройке corflags
.Вы должны избегать использования любых несовместимых функций, таких как Interop, во время выполнения.Однако - и это отличие от обычного использования режима /clr:safe
(который также создает библиотеку AnyCPU) - вы можете использовать небезопасные управляемые указатели для доступа к типам управляемых значений.[edit:] Чтобы пояснить комментарий Бена Войта, одна вещь, которую не будет работать в этом типе C ++ / CLI AnyCPU dll - это использование синтаксиса инициализации C / C ++ для инициализации неуправляемые (то есть собственные) статические примитивы, структуры или массивы:
static int my_arr[] = { 1, 2, 3 };
Компоновщик выдает предупреждение об этом warning LNK4210: .CRTMA section exists; there may be unhandled static initializers or terminators
.Однако вы можете объявить их, инициализировать их самостоятельно и использовать их - то есть взять их адреса - и прочитать / записать их из управляемого кода (если вы хотите объявить такой массив как const
, тогда вы 'Вам нужно будет предоставить пустые скобки { }
для инициализатора и привести указатель к volatile
для его инициализации.):
static int my_arr[3];
По иронии судьбы, один из способов инициализации этих собственных статических ресурсов или таблиц состоит в копированииони, во время конструктора модуля или статического конструктора класса, из управляемой переменной или ресурса.
Зачем беспокоиться о нативной статике, спросите вы?Потому что к ним можно быстро получить доступ без закрепления.Одна приятная вещь, которую C ++ / CLI все еще делает для вас, - это тихо создать управляемый тип-значение (структуру) для наложения каждой из ваших собственных статических функций, чтобы код IL мог получить к ним напрямую с помощью указателей IL, таким образом, сохраняя сборку / pure .
[править: исправлено неправильное утверждение относительно «родных» указателей в сборке AnyCPU] [править: уточнять: «небезопасный» код C # в чистой сборкеиспользует управляемые указатели через инструкции IL, такие как ldloca и т. д.]