Создание чистой сборки MSIL из проекта C ++ / CLI? - PullRequest
8 голосов
/ 14 июля 2011

Я пытаюсь создать чистую сборку MSIL из проекта C ++ / CLI, используя / clr: pure и / clrimagetype: pure flags, однако выходная сборка специально предназначена для x86.

Я что-то упускаю из-за того, что мой проект может быть скомпилирован только как MSIL?

Ответы [ 2 ]

13 голосов
/ 25 января 2012

Вы можете создать AnyCPU dll с C ++ / CLI , но в простейшем случае вы не сможете использовать MFC, ATL или CRT.Однако, если вы просто хотите написать чистый управляемый код .NET на C ++ / CLI, включая управляемые указатели (что не разрешено /clr:safe), и получить более сложную оптимизацию кода компилятора C ++ / CLI, читайте дальше:

  1. Для достижения наилучших результатов начните с нового проекта из шаблона проекта библиотеки управляемых классов.Установите свойства проекта C ++ / CLI для библиотеки классов DLL на /clr:pure.Это на странице Configuration Properties в Visual Studio 2010.
  2. На панели C / C ++ установите Omit Default Library Name на Yes /Zl
  3. Для компоновщика отключите Incremental Linking и Link Library Dependencies
  4. На странице «Дополнительно» компоновщика я установил для целевой машины значение Not Set, а для типа изображения CLR - Force Pure IL Image /CLRIMAGETYPE:PURE, но некоторые из этих видимых настроек не учитываются, поскольку флаг 32BIT +все еще устанавливается компоновщиком в заголовке PE32.
  5. Поэтому добавьте шаг 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.
  6. Наконец, добавьте запись-заглушку в исходный файл 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 и т. д.]

4 голосов
/ 14 июля 2011

Если вы используете Visual Studio, вы сможете установить свойство проекта Target Machine в Linker -> Advanced settings.

Если вам нужно скомпилировать ваш проект C ++ / CLI как «Любой процессор», то вам нужно скомпилировать в / clr: safe и / clrimagetype: safe. Смотрите следующую ссылку для получения дополнительной информации:

http://bytes.com/topic/net/answers/660475-any-cpu-build-c-cli

...