Как сделать def файл
кажется, что он заменяет необходимость использования явного экспорта в вашем DLL-коде (т. е. явный _ _ declspec (dllexport)) однако я не могу создать файл lib, когда не использую их, который затем создает проблемы компоновщика позже при использовании DLL.
Итак, как вы используете .defs при связывании с клиентским приложением они заменяют необходимость использования заголовка или .файл Либ?
мое понимание таково .def-файлы предоставляют альтернативу синтаксису _ _ declspec(dllexport) с дополнительным преимуществом-возможностью явного указания ординалов экспортируемых функций. Это может быть полезно, если вы экспортируете некоторые функции только по порядковому номеру, который не раскрывает столько информации о самой функции (например: многие функции экспорта внутренней DLL ОС только по порядковому номеру).
обратите внимание, что имена в .def-файл должен соответствовать именам в двоичном файле. Поэтому, если вы используете C или C++ с 'extern" C" <. >', имена не будут искажены; в противном случае вы должны использовать правильные искаженные имена для конкретной версии компилятора, используемого для создания DLL. Функция _ _ declspec () делает все это автоматически.
Я нахожу использование как _ _ declspec (dllexport), так и .def файл вместе, чтобы быть полезным при создании переносимых DLL, т. е. DLL, которые могут быть вызваны из кода, скомпилированного с другим компилятором или с другими настройками компилятора.
просто помещая _ _ declspec (dllexport) в объявления функций, эти функции будут "экспортироваться" вашей DLL (по крайней мере, в Windows), чтобы их можно было вызвать извне DLL.
однако, добавление в сборку a .защита файл, в котором перечислены все экспортированные функции, позволяет остановить компиляторы Microsoft (например) от добавления в имя экспортируемой функции информации о начальном подчеркивании и конечном параметре ширины (по крайней мере, в сочетании с директивой __stdcall, также полезной для переносимости). Е. Г. объявление функции
может в конечном итоге экспортироваться как "_foo@4", Если вы не будете осторожны с вызовом соглашения И.использование файла def.
сохранение экспортированной функции имена в таблице символов, свободные от такого имени-украшения, очень удобны при выполнении вызовов GetProcAddress() как часть загрузки и подключения к DLL явно во время выполнения. т. е. чтобы получить указатель на вышеуказанную функцию foo () (предполагая, что она была экспортирована вообще) во время выполнения, вы в идеале просто хотите вызвать:
С некоторой соответствующей проверкой случая ошибки, конечно!
использование a .def file plus _ _ stdcall, _ _ declspec (dllexport) и extern "C" в вашей функции объявления при создании библиотеки DLL гарантируют, что приведенный выше клиентский код будет работать для широкого спектра компиляторов и параметров компилятора.
для тех, кто заинтересован до сих пор. чтобы иметь возможность ссылаться на dll и def-файл, вам также требуется файл lib. В windows это можно сделать из def с помощью инструмента "LIB". См. ниже пример способа выполнения этого в командной строке.
надеюсь, это поможет другим.
Я не много работал с DLL, но я понимаю, что для экспортированных функций c++ вы должны использовать "__declspec(dllexport)", а для экспортированных функций C вы должны написать .def файл. Вероятно, это связано с тем, что функции C++ поддерживают перегрузку, а функции C-нет.
.DEF-файлы были более распространены в 16-битных окнах, где они обычно были единственным способом указать, какие символы должны быть экспортированы.
кроме того, они предоставили средства для указания экспорта по порядковому значению (@1, @2 и т. д.), а не по имени. Этот метод поиска символов использовался, когда производительность была действительно важна, например, в видеодрайверах.
мое понимание таково .def-файлы фактически не указывают, какие все API необходимо экспортировать. Он просто содержит экспортированные API и их порядковые номера. Если вы хотите фактически экспортировать определенный api, вам нужно указать __declspec(dllexport) в определении api и __declspec(dllimport) в объявлении.
преимущество def-файла заключается в том, что он помогает поддерживать совместимость backword с уже реализованными DLL. Я. e он поддерживает порядковые номера для API. Предположим, вы добавляете новый api в dll, затем компоновщик смотрит на ваш .def файл genearate порядковый номер для ne wapi таким образом, что порядковые номера для старых API неповреждены.
таким образом, если клиентский код использует последнюю dll, он не нарушает существующие API.
Проблема заключается в том, что использование стандартных lib-файлов от Майкрософт иногда приводит к ошибкам компиляции ассемблерного кода (например, сгенерированного дизассемблером IdaPro), связанных с отсутствием адекватных определений функций в файлах библиотек. Также нередко бывает ситуация, когда нужных либов просто нет, ни в MASM32, ни в MS Visual Studio. Скажем, файлы regapi.lib или utildll.lib и другие, для системных библиотек Windows, вы не найдете в стандартной поставке lib-файлов.
Кроме того, иногда возникает необходимость вызова функций по ординалам, что фактически сводится к вопросу вызова функции по ее псевдоимени или адресу.
Проблема вызова функций по ординалу в MASM32
Заметим, что конструкция MASM32
фактически является псевдокодом. В некоторых версиях ассемблера псевдокодом является также явный вызов по ординалу функции (ее номеру в таблице экспорта). Например, отладчик OllyDbg может для условного выражения
написать такой псевдокод
что означает вызов функции из модуля mfc42u.dll по ординалу 561.
Реальный код, эквивалентный этой конструкции, будет
Аналогичный пример, конструкция MASM32
или, в версии «Оли Дебаговой»,
эквивалентна реальному выражению
что уже непосредственно переводится в шестнадцатеричные команды процессора.
Итак, мы видим, что имена и ординалы не являются родными для процессора, однако компилятор MASM32 может автоматически перевести имена функций в их адреса, хотя не может сделать это для ординалов функций. Впрочем, это не большая потеря. Если мы не хотим пользоваться явной адресацией вместо вызова по ординалу, то у нас еще остается в запасе назначение псевдоимени функции без имени . Только сделать это можно в def-файле, из которого затем компилируется lib-файл. Соответственно, упоминавшиеся уже неадекватные описания функций, можно заменить в нашем def-файле на более корректные определения. Таким образом, мы со всей очевидностью приходим к необходимости иметь собственные def-файлы для нужных нам dll и возможности генерировать такие файлы автоматически.
Проблема универсальности в вызове функций
Еще один вопрос, связанный с универсальностью вызова функций, заключается в желании написать такой def-файл, чтобы можно было бы вызывать любое из выражений (без использования дополнительных определений, связанных с директивой equ) вида:
так как на практике встречаются все эти варианты.
Оказывается, подобное решение существует.
Универсальные def-файлы для простой программы
Действительно, создадим следующие файлы определений:
user32.def (где находится функция MessageBoxA)
и kernel32.def (где находится функция ExitProcess)
На их основе построим lib-файлы с помощью командного файла def2lib.bat
Файлы lib.exe и polib.exe можно взять из бесплатного пакета MASM32. Теперь, на основе этих библиотек напишем небольшую ассемблерную программу mb.asm.
В качестве lib-файлов, используем только что полученные библиотеки. На основе этого кода можно получить четыре варианта исполняемого файла (раскомментируя соответствующие строки). Обратим внимание, что первые два определения extrn содержат ключевое слово proc, а последние два – dword. Компилируем эту программу. Все четыре ее варианта дадут один и тот же результат (рис. 1).
Рис. 1. Результат выполнения программы mb.asm.
Нам интересно в ней то, что вызов функции мы можем осуществлять четырьмя различными способами, которые покрывают как стиль программирования Iczelion’a, так и стиль Ильфака Гильфанова (в его программе IdaPro). Только, в отличие от Iczelion’a, нам нет необходимости создавать или использовать чужие громоздкие inc-файлы.
Интересно, что пары файлов генерят практически идентичный бинарный код. Первая пара дает (в OllyDbg v. 1.10) код
Мы видим, что extrn . . . proc порождает переходники для системных функций, а extrn . . . dword – нет.
Все это, конечно, замечательно, однако для больших проектов нам нужны будут средства автоматизации или хотя бы механизации построения полных def-файлов для системных dll-ек и не только системных.
Если бы дело касалось только родных экспортируемых имен некоторой dll-ки, то мы могли бы взять за основу текстовый файл, генерируемой утилитой dumpbin из MS VS C++ или аналогичную программу. Однако нам нужны будут еще отладочные символы, а это значит, что придется работать с pdb-файлами от Майкрософт (для системных dll-ек). В идеале было бы хорошо написать свою утилиту, типа pdb2def.exe, преобразующей отладочные символы непосредственно в определения библиотечных файлов. Но для этого нужно знать формат pdb-файлов или API для работы с ними. Но до тех пор, пока это не будет сделано, можно воспользоваться более простым вариантом, хотя и немного громоздким. Хотя, как показывает опыт, без ручной корректировки созданных def-файлов не обойтись в любом случае. Не обязательно, делать все изменения сразу, да это практически и невозможно ибо Майкрософт не обеспечивает полного соответствия отладочных символов реально используемым. Однако имея под рукой полный def-файл, для данного системного dll-файла, всегда можно внести необходимые корректировки по ходу дела, компилируя затем, на его основе, lib-файл.
Получение def-файлов из листинга IdaPro для системных dll
Работая с листингами «Иды», легко обнаружить, что при условии использования отладочных символов, в них есть фактически вся информация, необходимая нам для формирования собственных def-файлов. Только эта информация «размазана» по всему листингу «Иды», поэтому нам придется писать внешний (потому, что демо-версия «Иды» не сохраняет результаты работы, иначе, как через буфер обмена) скрипт, который будет делать за нас всю необходимую работу.
Мы будем использовать IdaPro v. 5.7 demo. Для других версий «Иды» строки сигнатур (Line1 и Line2) могут отличаться (например, за счет использования пробелов вместо табуляторов или наоборот). Скрипт мы будем писать на Visual FoxPro. Вы можете использовать другой, более удобный вам язык, применяя похожий алгоритм.
Приведем сразу окончательный вариант нашего скрипта lst2def.prg, изучать который удобней всего в процессе работы. Если у вас будут какие-то замечания или предложения по его функционированию, то можете высказаться, используя контактную информацию. Конструктивная критика приветствуется .
Код скрипта lst2def.prg можно найти также в папке Prg прилагаемого файла с результатами исследований. Там же в качестве примера приложен листинг version.lst соответствующей dll-ки. Запуская на выполнение скрипт, получим в результате файл version.def (ненужные файлы удаляем). В папке Def находятся уже отредактированные вручную созданные, таким образом, файлы определений. Получая свои дефы, вы можете сравнить их с нашими.
Работа с программой Visual FoxPro
Наверное, пару слов надо сказать относительно Visual FoxPro. Кому-то нравится Perl для обработки текстовых файлов, а мне VFP. Для его работы (на уровне ядра) достаточно двух файлов, например, для 9-й версии VFP (годится и меньшая версия) это будут vfp9.exe (5.6 Мб) и vfp9enu.dll (1.5 Мб), которые можно взять непосредственно из любой инсталляции Visual FoxPro. Для исполнения скрипта достаточно записать в командной строке
в каталоге, где находится исходный файл листинга. Однако более удобно запускать программу Visual FoxPro в его собственной оболочке, назначив ассоциацию на файл *.prg (клавиша F10 в Total Commander) вида
Нажав Enter на файл lst2def.prg, мы загружаемся в IDE VFP, где мы можем отредактировать скрипт перед его исполнением (Ctrl+E). Есть еще варианты работы с runtime версиями, но, думаю, при желании, вы разберетесь с ними сами.
Ручное редактирование полученных def-файлов
Вот пример сгенерированного нашим скриптом файла определений mfc42u.def для mfc42u.dll, взятого из папки C:\WINDOWS\system32\ .
Скажем пару слов по структуре нашего def-файла. Как показывает запуск dumpbin.bat (dumpbin.exe взят из MS Visual Studio C++)
в файле mfc42u.dll практически все функции определены по ординалам
Поскольку экспортируемых имен функций в mfc42u.dll практически нет (за исключением первых шести), то наши имена определенные в mfc42u.def по сути являются псевдоименами, для определенности связанные явно с экспортируемыми ординалами. Когда же в dll-ке экспортируются имена, то нам уже нет необходимости и смысла указывать ординалы (которые могут быть скорее подвержены изменениям в будущих версиях библиотек, чем сами имена). Поэтому первые шесть функций (с их алиасами) указаны без ординалов.
В данном случае, для экспорта по ординалам, мы объявляем переменную
в результате чего ординалы функций указаны явно. Когда же нет необходимости экспортировать ординалы, то в этом случай мы пишем
в скрипте lst2def.prg. В смешанном же случае ситуация будет сложнее. Пока мы можем меньшую часть отредактировать вручную (до сих пор это не превышало несколько случаев на один файл). В перспективе, можно отслеживать экспорт по ординалу в исследуемом dll-файле (как это делает dumpbin.exe) для более корректной генерации def-файла. Тем не менее, если имя функции имеет алиас в отладочных символах, то этот случай подразумевает экспорт имен и наша переменная ToExportOrdinals игнорируется. В любом случае, вы всегда может подрегулировать данный скрипт под свои нужды.
Тестирование полученных lib-файлов
В качестве теста для созданных lib-файлов используем имеющиеся уже у нас asm-файлы из первых двух статей. Они также продублированы в каталоге Results. Содержимое соответствующей подпапки копируем на два уровня выше (туда, куда скопировано содержимое каталога write). Все подкаталоги с ассемблерным кодом содержат следующие командные файлы:
def2lib.cmd (для генерации 11-ти, используемых в нашем проекте системных lib-файлов) def2lib.bat (для создания только одного, явно указанного, lib-файла) asm.bat (один или несколько, для генерации соответствующего exe-шника, на базе созданных lib-файлов).
Пакетный файл def2lib.cmd достаточно запустить один раз, который из 11-ти def-файлов из папки Def сгенерирует такое же количество lib-файлов в папку Lib (изначально пустой). Если надо пересоздать какой-нибудь один lib-файл, то запускаем def2lib.bat (указав в нем нужное имя). asm.bat генерит непосредственно приложение, а если их несколько, то различные варианты этого приложения.
Для тестирования нам понадобятся наши собственные файлы:
advapi32.lib
imm32.lib
kernel32.lib
mfc42u.lib
msvcrt.lib
ntdll.lib
shell32.lib
shlwapi.lib
user32.lib
version.lib
В качестве исходных dll-файлов можно взять, в принципе, любые версии Windows NT помня только о различиях в составе функций разных версий NT и их сервис паков. В нашем случае, дефы, построенные по длл-кам Windows 2003 Server, sp. 2, работали под Windows XP, sp. 3 и наоборот.
Проблемы, возникающие при использование дефов / либов, полученных данным способом, возникают из-за неполноты информации в отладочных символах. Например, в листинге mfc42u.lst для mfc42u.dll можно встретить такой код
Это означает, что определена только одна функция
или, в записи понятной компилятору,
которая является телом следующих функций, определенных только по ординалам:
1016, 1055, 1747, 2015, 2016, 2017, 2474, 2977, 3074, 3101, 3142, 3254, 3744, 4043, 4103, 4112, 4383, 4564, 4650, 4666, 4721, 4876, 4974, 5010, 5501, 5508, 5523, 5524, 5526, 5549, 5559, 5561, 6051, 6320.
Всего 34 функции. Однако для этих ординалов, в exe-шниках (от Майкрософт), где они используются, могут быть определены их реальные имена. Скажем, в winmsd.exe, рассмотренном в прошлой статье, встречается импорт из mfc42u.dll этих функций не по ординалам, а по их реальным именам (известных только Майкрософту)
В нашем случае компилятор ругается на 12 функций, используемых в winmsd.asm, но определения которых отсутствуют в нашем mfc42u.def. Модифицируем этот def-файл. Вместо строки
созданной нашим скриптом, напишем
как в примере выше.
Проделав эту работу для остальных неопознанных линковщиком функций, мы получаем конечный, для данного теста, вариант файла mfc42u.def, который уже можно преобразовать в lib-файл.
Для других библиотек ошибки линковщика устраняются аналогично. Отметим только некоторые дополнительные нюансы.
В файле kernel32.def имя функции
заменили, с учетом информации «Иды», на
Просто оставить HeapSize не удается, так как функция «forwarded to NTDLL.RtlSizeHeap».
Некоторые функции имеют несколько алиасов. Так, например, в user32.def пришлось к записям
добавить еще одну
В shlwapi.def функцию _IsOS@4 пришлось явно определить по ординалу
(Смотрите по этому поводу предыдущую статью.)
Скомпилированный для обновленных lib-файлов winmsd.exe выполнился успешно. Все используемые def-файлы (кроме mfc42u.def) создавались с отключенным экспортом по ординалам (ToExportOrdinals = .F.). Исправлений в def-файлах было относительно немного для компилируемых нами asm-файлов, Все exe-шники работали без явных проблем. Впрочем, и внешних функций они использовали не очень много.
Просмотр структуры lib-файлов
Есть такая утилита PEview. Очень хороша для просмотра структуры lib-файлов (рис.2). При желании, вы можете пользоваться ею также.
Рис. 2. Просмотр lib-файла c помощью утилиты PEview.exe.
Выводы
Понятно, что представленное решение не является идеальным, И для новых проектов может потребоваться дополнительная правка def-файлов. Однако думается, что это будет вполне обозримым по трудоемкости. В любом случае, встречные предложения по совершенствованию техники создания собственных def и lib-файлов для различных dll только приветствуются.
Есть несколько DLL, требуется использовать функции из них в проекте на Си++. Доступа ни к исходникам ни к разработчикам у меня нет. То есть в наличии просто набор DLL как вешь в себе и документ с описанием интерфейса к ним.
Сейчас я получаю адреса функций вручную c помощью LoadLibrary и GetProcAdrress , но под мою задачу было бы удобнее иметь библиотеки импорта для них. Чтобы никаких телодвижений по инициализации не делать, не следить за ними и так далее. Так вот, как библиотеки импорта создать и вообще как они работают?
В принципе, это неподдерживаемый сценарий: например, функции могут быть декорированы нестандартным образом, или иметь нетрадиционное соглашение о вызове.
Но тем не менее, если вы знаете точную сигнатуру функций, то можно попытаться сделать, как описано здесь.
Идея №1: создать DEF-файл вручную. Это подойдёт, если функции, которые вы импортируете, есть C-функции, и вы знаете их calling convention (например, __cdecl или PASCAL ( __stdcall )).
Для начала, установим, что это за функции. Для этого можно воспользоваться стандартной утилитой dumpbin с ключом /exports (не забывайте, что её нужно запускать из-под Visual Studio command prompt) или очень полезной при нативной разработке под Windows-платформу утилитой depends.exe.
Для dumpbin вы получите примерно такой вывод:
Отсюда вы берёте имена функций: AnalyseW , CloseAnalyseW и т. д., и превращаете их в .def-файл:
Так работает для функций с calling convention __cdecl (она обычно принята по умолчанию). Для других вы должны задекорировать имя функции самостоятельно, согласно таблице:
(число после @ означает количество байт в стеке, отводимое под параметры).
Теперь можно использовать команду lib /def:yourfile.def из командной строки Visual Studio, чтобы построить .exp и .lib для линковки.
Идея №2 — это создать фейк-библиотеку с такими же сигнатурами функций, построить её, и использовать её .exp и .lib вместо отсутствующих. Для этого вам придётся построить С- (или хуже того, C++-) сигнатуры нужных функций. Для сишных функций (ну или тех, которые были определены как extern "C" в исходнике) это просто: вы смотрите на декорированное имя (например, в том же depends.exe или dumpbin), определяете по таблице сверху их calling convention, и кладёте такую функцию в исходник. Не забудьте указать __declspec(dllexport) для всех, и добавочно extern "C" для сишных функций. Реализуйте функции как угодно, чтобы компилятор скомпилировал это.
Если у вас декорированные C++-сигнатуры (они выглядят как-то так: ?test@@YGXXZ ) их можно превратить в правильные C++-декларации при помощи утилиты undname :
Если у вас есть header, идущий с библиотекой, то ничего угадывать (с риском ошибиться и получить креш) не надо, просто возьмите прототипы функций оттуда (только не забудьте поменять __declspec(dllimport) на __declspec(dllexport) ).
Скомпилируйте полученный файл в .obj при помощи команды
Ключ /c нужен, чтобы компилятор произвёл .obj, а /Ob0 — чтобы не занилайнил случайно какие-нибудь функции, которые ему покажутся ненужными (это может быть нужно в случае экспорта классов, и в любом случае не повредит).
Файлы определения модуля (.def) предоставляют компоновщику информацию об экспорте, функциях и других аспектах связанной программы. Файлы .Def наиболее полезны при создании DLL. Из-за существованияПараметры линкера, Обычно не требуют файлов .def. Вы также можете изменить__declspec(dllexport)Он используется как средство для указания экспортируемых функций.
Может использоваться во время фазы линкера/ DEF (указать файл определения модуля)Параметры компоновщика вызывают файл .def.
Если полученный файл .exe не экспортируется, использование файла .def приведет к увеличению размера выходного файла и замедлению загрузки.
каталог
Следующие правила синтаксиса применяются ко всем операторам в файле .def. Другие правила, которые применяются к конкретным утверждениям, объясняются с каждым утверждением.
В операторах, ключевых словах атрибутов и пользовательских идентификаторах учитывается регистр.
Длинные имена файлов, содержащие пробелы или точки с запятой (;), должны быть заключены в кавычки (").
Используйте один или несколько пробелов, табуляции или новых строк, чтобы отделить ключевые слова операторов от их аргументов и отдельных операторов. Укажите параметр с двоеточием (:) или знаком равенства (=), окруженным нулем или несколькими пробелами, символами табуляции или переводами строки.
Если вы используетеNAMEилиLIBRARYЗаявления, эти заявления должны предшествовать всем другим заявлениям.
В файле .defSECTIONSиEXPORTSЗаявление может появляться несколько раз. Каждый оператор может принимать несколько спецификаций, и каждая спецификация должна быть разделена одним или несколькими пробелами, символами табуляции или переводами строки. Ключевое слово оператора должно появляться один раз перед первой спецификацией и может повторяться перед каждой дополнительной спецификацией.
Многие операторы имеют эквивалентные параметры командной строки LINK. Для получения дополнительной информации см. Соответствующее описание опции LINK.
Комментарии в файле .def указываются точкой с запятой (;) в начале каждой строки комментария. Комментарии не могут совместно использовать одну строку с оператором, но могут появляться между спецификациями многострочного оператора. (SECTIONSиEXPORTSЭто многострочное утверждение. )
Укажите числовой параметр в десятичной или шестнадцатеричной форме.
Если строковый параметрЗарезервированные словаСовпадение, вы должны заключить строковый аргумент в двойные кавычки (").
Введен раздел, состоящий из одного или нескольких определений экспорта, которые указывают имя экспорта или порядковый номер функции или данных. Каждое определение должно быть в отдельной строке.
замечание
Первый definition Может и EXPORTS Ключевые слова находятся на той же строке или на следующей. Файлы .DEF могут содержать один или несколько EXPORTS Заявления.
экспорт definition Синтаксис:
entryname Имя функции или переменной для экспорта. Это обязательно. Если экспортируемое имя отличается от имени в DLL, используйте internalname Укажите имя, экспортируемое в DLL. Например, если DLL экспортирует функцию func1 И вы хотите, чтобы вызывающий абонент использовал его как func2 , Вы должны указать:
Поскольку компилятор Visual C ++ использует оформление имени для функций C ++, вы должны использовать имя оформления как entryname или internalname Или использовать в исходном коде extern "C" Определите функцию экспорта. Компилятор также изменит использование__stdcallВызовите обычную функцию C с префиксом подчеркивания (_) и суффиксом, состоящим из знака at (@), за которым следует число байтов в списке аргументов (в десятичном виде).
Чтобы найти оформленные имена, созданные компилятором, используйтеDUMPBINИнструмент или компоновщик/MAPПараметры. Декорированные имена зависят от компилятора. Если вы хотите экспортировать оформленные имена в файл .DEF, исполняемый файл, связанный с DLL, также должен быть сгенерирован с использованием той же версии компилятора. Это гарантирует, что оформленное имя в вызывающей стороне совпадает с именем экспорта в файле .DEF.
Вы можете использовать @ ordinal Указание порядкового номера вместо имени функции войдет в таблицу экспорта DLL. Многие библиотеки Windows экспортируют серийные номера для поддержки устаревшего кода. Обычно используются 16-битные серийные номера в кодировке Windows, потому что это помогает минимизировать размер DLL. Мы не рекомендуем делать это, если клиенту DLL не нужно экспортировать функцию по порядковому номеру для поддержки более старой версии. Поскольку файл .LIB будет содержать отображение между порядковыми номерами и функциями, вы можете использовать имена функций, как это обычно делается в проектах, использующих библиотеки DLL.
Используя опционально NONAME Ключевые слова можно экспортировать только по порядковому номеру и уменьшить размер таблицы экспорта в результирующей DLL. Однако, если вы хотите использовать его в DLLGetProcAddressВы должны знать серийный номер, потому что имя функции будет недействительным.
опциональный PRIVATE Ключевые слова запрещают entryname Включено в библиотеку импорта, созданную LINK. Это не влияет на экспорт изображений, которые также генерируются LINK.
опциональный DATA Ключевое слово указывает, что данные экспортируются, а не код. В этом примере показано, как экспортировать файл с именем exported_global Переменные данных:
Определения могут быть получены четырьмя способами, перечисленными в предлагаемом порядке:
В исходном коде__declspec(dllexport)ключевое слово
Файл .DEF EXPORTS заявление
Все четыре метода могут быть использованы в одной программе. LINK также создает библиотеки импорта при создании программ, включающих экспорт, если в сборке не используется файл .EXP.
Ниже приведен пример раздела ЭКСПОРТ:
При использовании файла .DEF для экспорта переменных из DLL вам не нужно указывать переменные __declspec(dllexport) , Однако в любом файле, который использует DLL, он все равно должен использоваться в декларациях данных. __declspec(dllimport) 。
Скажите LINK, чтобы создать DLL. LINK также создает библиотеки импорта, если в сборке не используется файл .exp.
замечание
libraryПараметр указывает имя библиотеки DLL. Вы также можете использовать/OUTОпция компоновщика указывает имя вывода DLL.
BASE=addressПараметр устанавливает базовый адрес, который операционная система использует для загрузки библиотеки DLL. Этот параметр переопределяет расположение DLL по умолчанию 0x10000000. Для получения дополнительной информации о базовых адресах см./BASEОписание варианта.
Не забывайте использовать DLL при сборке/DLLВарианты компоновщика.
HEAPSIZE экспонаты и/HEAPПараметры компоновщика одинаковы.
Определяет имя основного выходного файла.
замечание
Другой способ указать имя выходного файла - использовать/OUTОпция линкера, и другой способ установить базовый адрес - использовать/BASEВарианты компоновщика. Если указаны оба метода, / OUT переопределяетNAME。
Если создается DLL, NAME влияет только на имя DLL.
Введен один или несколько definitions (Спецификатор доступа для каждого раздела выходного файла проекта).
замечание
Каждое определение должно быть в отдельной строке. SECTIONS Ключевые слова могут находиться в той же строке, что и первое определение, или в предыдущей строке. Файлы .def могут содержать один или несколько SECTIONS Заявления.
что SECTIONS Оператор устанавливает свойства для одного или нескольких разделов в файле изображения и может использоваться для переопределения свойств по умолчанию для каждого типа раздела.
definitions Формат такой:
Здесь, .section_name Имя раздела в образе программы, specifier Доступ к модификаторам для одного или нескольких из следующих:
Модификаторы | объяснение |
---|---|
EXECUTE | Раздел исполняемый |
READ | Позволяет читать данные |
SHARED | Совместное использование разделов во всех процессах, которые загружают изображения |
WRITE | Разрешить запись данных |
Разделите имена модификаторов пробелами. Например:
SECTIONS Отметить часть definitions Начало списка. каждый definition Должно быть на отдельной строке. SECTIONS Ключевые слова могут быть такими же, как первые definition Ключевые слова находятся в той же строке или в предыдущей строке. Файлы .def могут содержать один или несколько SECTIONS Заявления. SEGMENTS Ключевые слова как SECTIONS Синонимы поддерживаются.
Более ранние версии Visual C ++ поддерживают:
По причинам совместимости, поддержка CLASS Ключевое слово, но игнорируется.
Другой способ указать характеристики раздела - это использовать/SECTIONПараметры.
Устанавливает размер стека в байтах.
замечание
Другой способ настроить стек - это использоватьРаспределение стека(/ STACK) опция. относящиесяreserveи commit Для получения дополнительной информации о параметрах см. Документацию по этой опции.
Эта опция не влияет на библиотеки DLL.
При использовании для создания файла определения модуля для драйвера виртуального устройства (VxD) STUB позволяет указать имя файла, содержащее структуру IMAGE_DOS_HEADER (определенную в WINNT.H), которая будет использоваться в VxD вместо заголовка по умолчанию.
замечание
Другое обозначениеfilenameМетод заключается в использовании/STUBВарианты компоновщика.
В файле определения модуля STUB действителен только при создании VxD.
Скажите LINK, чтобы поместить число в заголовок файла .exe или DLL.
замечание
majorиminorПараметр представляет собой десятичное число в диапазоне от 0 до 65 535. Значением по умолчанию является версия 0.0.
Другой способ указать номер версии - использоватьИнформация о версии(/ VERSION) вариант.
Интеллектуальная рекомендация
[Makefile от более мелких к более глубоким полная запись обучения 4] Переменные и различные методы присвоения
Давайте сегодня узнаем о различных методах присваивания переменных в Makefile! Смысл тяжелой работы, чтобы бедность больше не ограничивать свое воображение! Добавьте QQ, чтобы вместе учиться и обменив.
[Luogu P3147] [BZOJ 4576] [USACO16OPEN]262144
Портал Луогу БЗОЙ Портал Описание заголовка Bessie likes downloading games to play on her cell phone, even though she doesfind the small touch screen rather cumbersome to use with her large hooves. Sh.
;Это тип объекта. Game_entity - декорация, actor - активный объект (напр. техника). Есть и другие.
;Если дальше идет вызов файла свойств, то неважно, что тут стоит.
(include "/properties/armoredcar.ext")
;Файл, где прописаны основные свойства объекта. Копировать из похожей техники. Два указывать нельзя.
(include "/properties/shadow/tank.inc" scale(1.4))
(include "/properties/selection/vehicle.inc" scale(1.2))
;Эти два файла отвечают за тени и круги выделения. Копировать из похожей техники.
;Нечто, отвечающее за ИИ. Копировать из похожей техники, если нет - не беда, вероятно.
;Отвечает за механику столкновений. Копировать из похожей техники.
;armored_car_M - колесная техника (БТР и БМП), поддерживающая AAS. Тут может быть "car" для авто, "light_M" для гусеничных БТР и БМП,
;"medium_M" для танков без многослойной брони, "heavy_M" для современных танков с толстой многослойной лобовой броней.
;"vision_lev06" - отвечает за заметность. Чем больше цифра - тем лучше видно. Свое не выдумываем, копировать из похожей техники.
;"turret" - отвечает за отрыв башни
;"wheeled" - колесная техника
;"8_wheels" - отвечает за ходовую - без скольких колес едет. Указывать, конечно, общее число колес - 8, 6, 4.
;"tank" общие свойства бронетехники
;"with_gun" - обработка пушки.
("armor_light_btr" turret(12 12 12 12) body(12 12 12 12))
;тут указываем тип брони
;armor_light_btr - менее 15мм лоб, только если указано "/properties/armoredcar.ext" Остальные для "/properties/tank_unarmed.ext":
;armor_light - менее 15мм лоб для гусеничной техники.
;armor_IFV - 15-25мм лоб
;armor_medium - выше 25мм, но не многослойная. Для старых танков.
;armor_heavy - для новых танков.
;turret(12 12 12 12) - лоб/борт/корма/крыша-и-днище башни, а далее - для корпуса.
;далее - про экипаж. Для каждого члена экипажа надо:
;1. анимация залезания/вылезания. Пишется в boarder
; ; >
; >
; >
; ; ; - это анимация при начале процесса. - анимация при конце процесса, - анимация техники.
;-1 после названия анимации означает, что анимация играется в обратном направлении.
;В нашем случае: при залезании члена экипажа с группой анимаций driver он сначала проигрывает у себя board_tank_left,
;а после нее ничего не проигрывает, т. к. нет блока . При этом DANA запускает анимацию open_driver.
;(забегая вперед скажу, что мехвод танка не виден, поэтому нет . Если же человек виден, то в
;пишется его поза. например, для машины в пишем анимацию залезания, а в - позу на сиденье).
;2. Placer
; ; ; ;Член экипажа или пассажир
; ;Если виден снаружи, то это кость, где он сидит.
; > ;вырубаем тень и вырубаем визор (можно не вырубать, но если вырубили - нужно назначить другой)
;Если должен быть виден, но не хотите, чтобы ИИ в него стрелял - >
; ;может завалить обломками
; ;каким визором техники пользуется.
; >
; >
;3. Двери. в boarder
;
; >
; - объявляет такую дверь. Если хотите задать сложный путь по технике (локомотив или плавсредство) - нужны еще node.
; > - это значит, что на место gunner2 попадают через emit3
;с анимацией "gunner2"
("crew_human" place(driver) door(emit1) group(crew) animation(driver) visor(driver))
("crew_human" place(commander) door(emit2) group(crew) animation(commander) visor(driver))
("crew_human" place(gunner) door(emit4) group(crew) animation(gunner) visor(main))
("crew_human" place(charger) door(emit4) group(crew) animation(charger) visor(main))
>
>
>
;Блок визоров. перечислены визоры техники, а кто в них смотрит - распределено выше. Если визор не прописан ни для кого, то им пользуется любой.
;
;Частично визоры прописаны и в ext выше (2 строчка), поэтому в def вы только прописываете недостающее.
;По умолчанию:
; ; ;у танка маленько другой, - но неважно
;
; >
; ;
;
; >
;Мы здесь заменяем в визоре "main" (прицел наводчика) тип визора на
; и добавляем третий визор "top".
;Типы визоров CW:
;"tank_gunner_optic_1g", "tank_gunner_optic_2g", "tank_gunner_optic_3g" - прицельные комплексы с кратностью 1х-4х, 5х-8х и 9х и выше соответственно.
;"tank_gunner_optic_IR_1g", "tank_gunner_optic_IR_2g", "tank_gunner_optic_IR_3g" - то же самое, но если есть ночное видение.
;"radar_sharp" - узкий радарный луч вращающихся радаров, дальность обнаружения ок. 15 км
;"radar_wide" - если радар движется под колпаком, и движения не видно - такой же радар.
;"radar_around" - радар кругового обзора, дальность та же. На Апаче, например.
;"aircraft_optic_IR_1g" - просто авиационный ночник, без увеличения.
;"aircraft_optic_2g" - авиаприцел до 15х (прим. "aircraft_optic_1g" нет. ) без ночного канала, "aircraft_optic_IR_2g" - с ночным каналом
;"aircraft_optic_3g" - ПРПНК кратностью выше 15х - Ка-50
;"aircraft_optic_IR_3g" - то же, но с ночным каналом (в моде пока нет)
;Блок вооружения
("restore_ik_time")
;что-то про восстановление положения после отдачи. Не нужно, работает только у БТР.
;Это название ствола. "gun" - пушка, "gun1" - доп. пушка, "gun2" "gun3" - пусковые ПТУР, "mgun*" - пулеметы.
;оружие - 152mm_2A64, заправлено "ammo bullet152_RUS fg" в количестве 1
;кто стреляет
;кто заряжает
("abm_18")
;точность стрельбы в движении.
;якобы стрельба с места, но не работает.
>
;это кость, откуда летит снаряд. У пушки не писали, там
("abm_mgun_heavy")
;Вот это не знаю.
>
>
("wheel" args "wheelright1")
("wheel" args "wheelleft1")
("wheel" args "wheelright2")
("wheel" args "wheelleft2")
("wheel" args "wheelright3")
("wheel" args "wheelleft3")
("wheel" args "wheelright4")
("wheel" args "wheelleft4")
;перечисляем колеса, чтобы отрывались.
;Далее блок шасси, но с ним я пока не работал. Главное там -скорость.
; реверс коробки передач
>
("car_trace" fx("tracewheel02") step(0.09) wheell("wlf") wheelr("wrf") bonel("FXtraceL1") boner("FXtraceR1"))
("car_trace" fx("tracewheel02") step(0.09) wheell("wlr") wheelr("wrr") bonel("FXtraceL2") boner("FXtraceR2"))
("car_trace" fx("tracewheel02") step(0.09) wheell("wlf") wheelr("wrf") bonel("FXtraceL3") boner("FXtraceR3"))
("car_trace" fx("tracewheel02") step(0.09) wheell("wlf") wheelr("wrf") bonel("FXtraceL4") boner("FXtraceR4"))
; liters
;0.35*20 > ; liters per kilometer
>
>
Читайте также: