Как построить приложение - Словарик
.RU

Как построить приложение - Словарик


^ Как построить приложение
После разработки исходного текста приложения возникает необходимость его скомпилировать и построить файл образа задачи (выполняемый файл, exe–файл). В книге не будет даваться подробное описание конкретных методов построения приложений — эту информацию стоит почерпнуть из руководств по вашему компилятору. В зависимости от применяемой среды разработки приложений и даже от способа ее применения процесс построения приложений будет изменяться.

В данном разделе будут рассмотрены только основные шаги, из которых состоит построение приложения для Windows и исходные файлы, которые могут для этого потребоваться. Все среды построения приложений будут так или иначе реализовывать эти шаги и разработчику надо будет ориентироваться в тех исходных файлах, которые будут применяться или создаваться в процессе генерации выполняемого файла.
^ Как строили Windows–приложения в самом начале
Предварительно начнем с истории, времен ранних версий Windows (до 3.x). В те времена, когда Windows только начинал развиваться, компиляторы не содержали практически никаких средств поддержки процесса создания приложений для Windows. В этом случае практически вся работа сваливалась на программистов, которые должны были разрабатывать дополнительные текстовые файлы, необходимые для построения приложений.

Основные сложности были связаны с двумя особенностями приложений для Windows:

Обычная DOS–задача не могла делать таких вещей. Поэтому в Windows был принят новый формат выполняемого файла, а для нормального построения образа задачи пришлось изменить стандартный компоновщик (linker) так, чтобы он мог использовать информацию об экспортируемых и импортируемых функциях и собирать выполняемые файлы в новом формате. Соответственно, такой компоновщик нуждался в информации об экспортируемых и импортируемых функциях, а также о некоторых дополнительных параметрах Windows–приложения. Чтобы предоставить эту информацию компоновщику надо было написать специальный текстовой файл — файл описания модуля (def–файл).

В файле описания модуля перечислялись имена экспортируемых функций, имена импортируемых и библиотеки, содержащие функции, подлежащие импорту, задавался размер стека, давалось короткое описание приложения и пр. Это было не слишком удобно, так как при вызове какой–либо новой функции из Windows API (а их более 1000), необходимо было добавлять ее имя в файл описания модуля.

В тех случаях, когда приложение нуждалось в собственных ресурсах, необходимо было отдельно описать эти ресурсы в специальном текстовом файле описания ресурсов (rc–файле). Вместе с компиляторами до сих поставляется специальный компилятор ресурсов RC.EXE, который воспринимает файл описания ресурсов, компилирует его и создает файл ресурсов приложения (res–файл). Затем тот–же компилятор ресурсов может объединить уже построенный выполняемый файл с файлом ресурсов приложения.

Таким образом построение приложения состояло из следующих этапов:

Конечно, если собственных ресурсов приложение не имело, то построение задачи несколько упрощалось. Но и при этом необходимость перечислять все экспортируемые и импортируемые функции в файле описания приложения была крайне неудобной.
^ Следующий этап
Очевидно, что необходимость перечислять кучу имен функций в файле описания приложения никого не приводила в восторг. Поэтому на следующем этапе была включена поддержка Windows–приложений непосредственно в компиляторы21. Для этого было добавлено ключевое слово _export (иногда __export), которое применяется при описании экспортируемых функций непосредственно в тексте C–программы. Для таких функций компилятор включает в объектный файл специальную информацию, так что компоновщик может правильно собрать выполняемый файл. Так, например, было сделано в первом примере для оконной процедуры:

LRESULT WINAPI _export proc( ...

Помимо экспортированных функций, в файле описания приложения было необходимо перечислять все импортированные функции. А этот список был самым большим (Windows экспортирует более 1000 функций, которые могут импортироваться приложениями). Для решения этой задачи был изменен формат библиотек объектных файлов, так что появилась возможность описать имена функций, экспортированных другими модулями. Так компоновщик задачи может определить, какие функции импортируются и из каких модулей.

В этом случае составление файла описания модуля стало тривиальным — длинные списки имен экспортированных и импортированных функций исчезли, а остальная информация заполнялась, как правило, однообразно для разных приложений. Компоновщики задач получили возможность обходиться вообще без файлов описания модуля — при его отсутствии подставлялись стандартные значения. С этого момента простейшее приложение можно было создать, написав только один файл с исходным текстом программы.

Библиотеки со списками функций, которые можно импортировать из Windows (то есть экспортированных компонентами Windows) входят в состав всех компиляторов. Иногда может возникнуть необходимость использования нестандартного компонента (или собственной динамически загружаемой библиотеки), для которых соответствующей библиотеки с ссылками нет. В таком случае можно воспользоваться специальным приложением — implib.exe — которое входит в состав большинства компиляторов (если его нет в составе компилятора, то значит его возможности реализованы в каком–либо другом инструменте, как, например, wlib.exe в Watcom C/C++). Implib позволяет по имеющемуся файлу динамически загружаемой библиотеки (.dll) или файлу описания проекта модуля библиотеки (.def), содержащему список экспортированных функций, построить библиотечный файл (.lib), с ссылками на функции библиотеки.

Первоначально, стремясь максимально уменьшить время загрузки модулей в память, при экспортировании функций им присваивались уникальные номера (назначаются разработчиком, либо просто по порядку). Конкретная функция однозначно определяется именем экспортирующей библиотеки динамической загрузки и идентификатором функции. Для задания идентификаторов экспортируемых функций используется файл описания модуля. Однако использование номеров вместо имен является не слишком удобным для человека, поэтому в Windows используются оба метода — функции доступны как по их идентификаторам, так и по их именам. Для Windows API общепринятым методом считается использование идентификаторов — Microsoft следит за тем, что бы все документированные функции сохраняли свои идентификаторы. А в Win32 API предполагается использование имен; более того, Microsoft не гарантирует, что идентификаторы документированных функций не будут изменяться.

Построение приложения сохранило в себе все шаги, однако создание файла описания приложения стало необязательным. При разработке приложений для Win32 API с файлами описания модуля практически не приходится иметь дело, он используется в очень редких случаях для построения динамически загружаемых библиотек. В настоящее время и в случае Windows API, и в случае Win32 API этот файл создается только если необходимо обеспечить нестандартную компоновку модуля, имеющего, например, разделяемые сегменты данных.

Современные компиляторы и системы поддержки проектов фактически остались в рамках рассмотренного порядка построения приложения. Небольшие изменения реализованы в разных компиляторах независимо друг от друга. Так, иногда включение файла ресурсов приложения в выполняемый модуль выполняется не компилятором ресурсов, а непосредственно компоновщиком; в других случаях специальные редакторы ресурсов позволяют обойтись без построения файла описания ресурсов (.rc), а создать непосредственно файл ресурсов приложения (.res). Особенно часто это делается в системах визуального программирования.

Если вы используете какую–либо систему поддержки проектов (Watcom IDE, Microsoft Developer Studio, Borland IDE, Symantec IDE и пр.) — а скорее всего это именно так — то вы должны только проследить за тем, что бы необходимые файлы были включены в проект. Система сама отследит, как и когда должен использоваться тот или иной исходный файл.

Обычно в проект включаются следующие файлы:
^ Файл описания модуля (.def)
Файл описания модуля (приложения) содержит обычный текст, который можно написать любым текстовым редактором. В качестве примера рассмотрим один из файлов описания модуля, использованный для построения приложения testapp.exe:

^ NAME TESTAPP
DESCRIPTION 'TESTAPP - test application'
EXETYPE WINDOWS
PROTMODE
STUB 'WINSTUB.EXE'
CODE LOADONCALL MOVEABLE
DATA MOVEABLE MULTIPLE
STACKSIZE 8192
HEAPSIZE 4096

В этом файле отсутствуют списки экспортированных и импортированных функций, так как использовался компилятор для Windows 3.1, осуществляющий связывание с импортированными функциями с помощью библиотек. Сейчас мы рассмотрим информацию, которая может размещаться в этом файле.

Большинство компиляторов могут использовать собственные директивы, а также собственные расширения для параметров, задаваемых в директивах, не описанные в общих руководствах (как, к примеру, директива PROTMODE в приведенном примере). Кроме того список возможных директив в файлах описания модулей для Windows API и для Win32 API различается.
^ Windows API
Первая строка обычно задает имя модуля. Если вы строите приложение, то первой должна стоять директива NAME, а если динамически загружаемую библиотеку — LIBRARY. Указание обоих директив считается некорректным. Имя должно соответствовать имени файла, так для testapp.exe эта строка будет такой: NAME TESTAPP, а для mydll.dll — LIBRARY MYDLL.

LIBRARY dllname
NAME exename

Обычно следующая строка — описание данного модуля. Она начинается с директивы DESCRIPTION, за которой следует произвольный текст, заключенный в апострофы:

DESCRIPTION ‘description text for module’

Следующая директива, если и присутствует, то всегда определяет, что данный модуль предназначен для работы в среде Windows (аналогичные файлы описания модулей могут применяться для OS/2).

^ EXETYPE WINDOWS

Еще две директивы предназначены для задания размеров стека и кучи. Задание размера стека менее 5K приводит к тому, что Windows сам увеличивает его до 5K. Задание размера кучи вообще абстрактно — главное, что бы не 0, так как Windows будет увеличивать кучу при необходимости (вплоть до наибольшего размера сегмента данных приложения — 64K). Размер кучи 0 говорит о том, что она просто не используется..

HEAPSIZE size
STACKSIZE size

Очень любопытная директива — STUB. О ней надо рассказать чуть подробнее. Ранее было отмечено, что для Windows–приложений был разработан собственный формат выполняемого модуля. Очевидно, что попытка запустить такой модуль на старой версии DOS, который не рассчитан на такую возможность, приведет к грубой ошибке, вплоть до зависания компьютера или порчи данных. Чтобы этого избежать, сделали так — Windows–приложение состоит из двух частей:

STUB ‘stubexe.exe’

Здесь stubexe.exe — имя приложения–заглушки (возможно полное имя, вместе с путем)

Разрабатывая собственную заглушку можно делать интересные приложения, работающие в DOS и в Windows. Скажем, собрать в один выполняемый файл DOS–версию приложения и Windows–версию.

Еще три директивы используются для описания параметров сегментов кода и данных. Директива CODE задает характеристики сегментов кода, DATA — сегментов данных, а SEGMENTS позволяет описать характеристики для конкретного сегмента (в квадратные скобки [] заключены необязательные параметры, знак | разделяет возможные варианты; запись [FIXED|MOVEABLE] означает, что может быть указано либо FIXED, либо MOVEABLE, либо ничего). Более подробно о характеристиках сегментов приложения см. в описании диспетчера памяти Windows 3.x.

^ CODE [FIXED|MOVEABLE] [DISCARDABLE] [PRELOAD|LOADONCALL]

DATA [NONE|SINGLE|MULTIPLE] [FIXED|MOVEABLE]

SEGMENTS
segname [CLASS ‘clsname’] [minalloc] [FIXED|MOVEABLE] [DISCARDABLE] [SHARED|NONSHARED] [PRELOAD|LOADONCALL]
...

Могут быть указаны следующие параметры: FIXED или MOVEABLE — сегмент фиксирован в памяти или перемещаемый; если сегмент перемещаемый, то он может быть теряемым (DISCARDABLE). Параметры PRELOAD и LOADONCALL указывают, когда сегмент должен быть загружен в оперативную память — при загрузке приложения (PRELOAD) или при непосредственном обращении к нему (LOADONCALL). Параметры NONE, SINGLE или MULTIPLE применяются только для сегментов данных. NONE или SINGLE применяется для динамически загружаемых библиотек; NONE — библиотека не имеет сегмента данных вообще, SINGLE — сегмент данных присутствует в памяти в единственном экземпляре (динамические библиотеки загружаются только один раз, других копий не существует, все приложения ссылаются на одну библиотеку с единым сегментом данных). MULTIPLE — сегмент данных загружается для каждой копии приложения, применяется только для приложений.

Директива SEGMENTS описывает характеристики конкретных сегментов; segname — имя сегмента, clsname — имя класса сегмента, minalloc — минимальный размер сегмента. SHARED или NONSHARED сообщает, является ли сегмент разделяемым разными копиями приложения, либо нет. После одной директивы SEGMENTS может размещаться описание нескольких сегментов, по одному на каждой строке.

Еще две часто используемых директивы — EXPORTS и IMPORTS. Они задают списки экспортированных и импортированных имен функций, описание каждой функции находится на своей строке. В обоих случаях надо учитывать следующую особенность — в Windows различают внешние и внутренние имена. Внутренние имена — это имена, использованные при разработке исходного текста программы, те которые содержаться в тексте C–программы (или в объектном файле). Внешние имена — имена используемые при экспорте/импорте, доступные другим модулям. Внешнее и внутреннее имя могут не совпадать, поэтому предусмотрена возможность задавать оба имени.

EXPORTS
exportname [=internalname] [@id] [RESIDENTNAME] [NODATA] [argsize]
...

В разделе EXPORTS перечисляются имена функций, экспортируемых данным модулем. Параметр exportname задает внешнее имя функции, под которым она будет доступна другим модулям, параметр internalname используется, если внешнее и внутреннее имена различаются, @id задает идентификатор функции, argsize — если указан, сообщает сколько слов в стеке занимает список аргументов функции. Параметры RESIDENTNAME и NODATA используются крайне редко; RESIDENTNAME говорит о том, что имя функции должно размещаться в так называемом резидентном списке имен (который находиться в памяти постоянно после загрузки модуля), обычно имена размещаются в нерезидентном списке, который загружается при необходимости. NODATA говорит о том, что функция использует сегмент данных вызывающего модуля, а не экспортирующего (подробнее — при разговоре о диспетчере памяти).

IMPORTS
[internalname=] modulename.id
[internalname=] modulename.importname

Раздел IMPORTS задает соответствие внутренних имен импортируемых функций (internalname) функциям, экспортированным другими модулями. Возможно два метода связывания имен — по идентификатору (первый пример), modulename — имя экспортирующего модуля, id — идентификатор; либо по именам (второй пример), importname — внешнее имя функции, под которым она была экспортирована другим модулем.
^ Win32 API
Файл описания модуля в Win32 API используется для задания нестандартных характеристик динамически загружаемых библиотек. Полное описание файлов описания модуля для Win32 API надо смотреть в документации, сопровождающей применяемый компилятор.

Так как файл описания модуля используется для создания DLL, то первая директива — LIBRARY. Часто применяется также директива EXPORTS для задания идентификаторов экспортируемых функций (обе — см. в описании файла описания модуля для Windows API).

Для задания нестандартных параметров отдельных сегментов используется директива SECTIONS, заменяющая прежнюю директиву SEGMENTS. Синтаксис директивы SECTIONS несколько иной, хотя допускается замена слова SECTIONS на SEGMENTS:

SECTIONS
secname [CLASS ‘classname’] [EXECUTE] [READ] [WRITE] [SHARED]

После указания имени секции (сегмента) следует необязательное указание имени класса и атрибутов этой секции — разрешение на выполнение (EXECUTE), на чтение (READ), на запись (WRITE) и объявление секции разделяемой (SHARED) между разными копиями модуля (загруженными в разных адресных пространствах разных приложений!).

kakov-mehanizm-dejstviya-belkovih-gidroliza-tov-obshij-uhod-za-bolnimi-osnovnie-lechebno-diagnosticheskie-proceduri.html
kakova-funkciya-centralnogo-rechevogo-apparata-i-ego-otdelov-programma-disciplini-dpp-f-02-logopediya-celi.html
kakova-zhe-prichina-avarii-otchet-o-provedenii-ekologicheskogo-uroka-dlya-shkolnikov.html
kakovi-osnovnie-funkcionalnie-vozmozhnosti-sovremennih-tablichnih-processorov-chto-takoe-informacionnaya-tehnologiya.html
kakovi-predposilki-sovershenstvovaniya-sistemi-upravleniya-portfelem-proektov-v-kompanii-v-usloviyah-krizisa.html
kakovi-sostav-i-naznachenie-operacij-formatirovaniya-tekstovogo-dokumenta-chto-takoe-informacionnaya-tehnologiya.html
  • obrazovanie.bystrickaya.ru/predvaritelnaya-programma-konferencii-vklyuchaet-rabotu-po-sleduyushim-sekciyam-1-genetika-i-biotehnologiya-v-zhivotnovodstve.html
  • writing.bystrickaya.ru/atomnaya-energiya.html
  • thesis.bystrickaya.ru/poryadok-vedeniya-nalogovogo-ucheta-rashodov-na-remont-osnovnih-sredstv.html
  • institute.bystrickaya.ru/glava-27-zhizn-v-zelyonom-cvete.html
  • school.bystrickaya.ru/formi-beznalichnih-raschetov.html
  • abstract.bystrickaya.ru/02042010molodoj-kommunar-tulasluzhit-bi-rad-analiz-upominaemosti-v-smi-romir-i-konkurentov-obzor-smi-za-05-aprelya-2010-god.html
  • universitet.bystrickaya.ru/tablica-kraevogo-festivalya-studencheskogo-tvorchestva-festa-2011.html
  • studies.bystrickaya.ru/biznes-plan-kompyuternaya-kompaniya-chast-7.html
  • nauka.bystrickaya.ru/vojni-svyashennie-stranici-naveki-v-pamyati-lyudskoj-stranica-3.html
  • nauka.bystrickaya.ru/upravlenie-vnutrennih-del-hanti-mansijskogo-avtonomnogo-okruga-okruzhnoj-otdel-vnutrennih-del.html
  • kanikulyi.bystrickaya.ru/zaklyuchenie-vneshnetorgovogo-kontrakta-chast-11.html
  • uchitel.bystrickaya.ru/raba-fobij-irina-majorova-metromaniya.html
  • znaniya.bystrickaya.ru/rabota-psihologa-konsultanta-i-psihoterapevta-v-sovremennom-rossijskom-obshestve.html
  • essay.bystrickaya.ru/chastya-kak-obresti-krepkuyu-veru-v-boga.html
  • spur.bystrickaya.ru/korabli-idut-po-minnim-polyam-petr-iosifovich-kapica-v-more-pogasli-ogni.html
  • holiday.bystrickaya.ru/nazvanie-stati-na-russkom-yazike.html
  • school.bystrickaya.ru/chempion-birzhevogo-turnira-2012-andrej-beritc-vistupit-na-seminare-eltri.html
  • college.bystrickaya.ru/136-obshirnij-interfejs-zakonchennij-uchebnik-i-rukovodstvo-po-yaziku.html
  • tasks.bystrickaya.ru/3-cel-uroka.html
  • literatura.bystrickaya.ru/sbornik-duhovnih-gimnov-i-pesen-evangelskih-cerkvej-stranica-63.html
  • znanie.bystrickaya.ru/8-tuman-nad-bolshimi-kurganami-predislovie.html
  • university.bystrickaya.ru/glava-pervaya-pravila-igri-dlya-umnih-viktoriya-isaeva.html
  • gramota.bystrickaya.ru/zakonotvorcheskaya-deyatelnost-rossijskih-liberalov-stranica-8.html
  • upbringing.bystrickaya.ru/list-vkladka-rabochej-programmi-uchebnoj-disciplini-s-dopolneniyami-i-izmeneniyami-1-poyasnitelnaya-zapiska-stranica-6.html
  • college.bystrickaya.ru/16-etazhnij-zhiloj-dom-s-monolitnim-karkasom-v-g-krasnodare-chast-12.html
  • klass.bystrickaya.ru/7filosofskij-enciklopedicheskij-slovar-red-sostefgubskij-i-dr-2003-g.html
  • bukva.bystrickaya.ru/modernizaciya-mini-kolbasnogo-ceha-chast-7.html
  • upbringing.bystrickaya.ru/kot-kotkin-yurij-magalif.html
  • crib.bystrickaya.ru/govorit-o-plohoj-proforientacii-rektor-rggu-the-collection-comprises-talks-and-interviews-given-by-dr-pivovar.html
  • college.bystrickaya.ru/-kistyunina-l-b-stranica-2.html
  • doklad.bystrickaya.ru/uchebnoe-posobie-znakomit-chitatelya-s-tehnikoj-eksperimenta-v-himii-i-prednaznacheno-dlya-obucheniya-osnovnim-priemam-raboti-v-himicheskoj-laboratorii-stranica-5.html
  • assessments.bystrickaya.ru/ekzamen-informaciya-dlya-studentov-zaochnikov-pri-oformlenii-kontrolnoj-raboti-sleduet-rukovodstvovatsya-pravilami-izlozhennimi-v-standarte.html
  • teacher.bystrickaya.ru/glava-6-definicii-v-pravovih-aktah-zadacha-tochnogo-adekvatnogo-nedvusmislennogo-virazheniya-v-pravovih-aktah-voli.html
  • zadachi.bystrickaya.ru/municipalnoe-pravo-kak-otrasl-nauki.html
  • shkola.bystrickaya.ru/termalnie-i-mineralnie-vodi-kamchatki.html
  • © bystrickaya.ru
    Мобильный рефератник - для мобильных людей.