Иллюстрированный самоучитель по Macromedia Flash MX. Статические и динамические библиотеки - лекция Краткая история процесса создания программы

MKSHLIB(1)

НАЗВАНИЕ
mkshlib - создание разделяемой библиотеки

СИНТАКСИС

Mkshlib -s файл_спецификаций [-t библ_выполнения] [-h библ_сборки] [-n] [-L каталог] [-q]

ОПИСАНИЕ
Команда mkshlib создает как разделяемые библиотеки выполнения, так и разделяемые библиотеки сборки. Разделяемая библиотека очень похожа на обычную, неразделяемую об ектную библиотеку, но отличается тем, что программы, собранные с разделяемой библиотекой, будут во время выполнения пользоваться одним и тем же экземпляром секций команд библиотечных подпрограмм, тогда как в случае неразделяемых библиотек в каждом процессе имеется своя копия библиотечных подпрограмм.

Разделяемая библиотека сборки - это архив, который используется при редактировании связей между программами пользователя и разделяемой библиотекой [см. ar(4) ]. С разделяемой библиотекой сборки можно работать точно так же, как и с неразделяемой, она может обычным образом включаться в команду cc(1) . Кроме того, все операции, которые можно выполнять над архивом, могут быть выполнены и над разделяемой библиотекой сборки.

Разделяемая библиотека выполнения - это выполняемый модуль, который присоединяется к процессу пользователя во время выполнения программы, использующей разделяемую библиотеку. Разделяемая библиотека выполнения содержит секции команд всех подпрограмм библиотеки; в ней не должно быть неразрешенных ссылок. Разделяемая библиотека выполнения будет загружена в память во время выполнения программы, использующей разделяемую библиотеку, и другие процессы, использующие ту же библиотеку, будут разделять уже загруженные в память секции команд, но каждый процесс будет иметь свою копию секции данных.

Интерфейс пользователя с командой mkshlib состоит из опций командной строки и файла спецификаций, описывающего содержимое разделяемой библиотеки.

Команда mkshlib производит вызов других программ, таких как ar(1) , as(1) , ld(1) . Обращение к другим программам происходит с помощью системного вызова execvp [см. exec(2) ], который ищет нужную программу в каталогах из списка поиска, хранящегося в переменной PATH. Команда mkshlib обрабатывает префиксы так же, как и команда cc(1) ; все программы, к которым производится обращение, получают тот же префикс. Например, pfxmkshlib вызовет pfxld.

Команда mkshlib распознает следующие опции: -s файл_спецификаций Указывает файл спецификаций разделяемой библиотеки. Этот файл содержит информацию, необходимую для построения разделяемой библиотеки. В нем находятся спецификации таблицы переходов для разделяемой библиотеки выполнения, маршрутное имя файла, в котором должна находиться разделяемая библиотека выполнения, начальные адреса секции команд и секции данных для разделяемой библиотеки выполнения, спецификации инициализации для разделяемой библиотеки сборки и список об ектных файлов, которые должны быть включены в разделяемую библиотеку (подробности см. ниже).

T библ_выполнения Указывает файл, в который будет помещена создаваемая разделяемая библиотека выполнения. Для того, чтобы воспользоваться разделяемой библиотекой выполнения, ее необходимо переместить в то место, которое указано в файле спецификации (см. ниже директиву #target). Если используется опция -n, генерации разделяемой библиотеки выполнения не производится.

H библ_сборки Указывает файл, в который будет помещена создаваемая разделяемая библиотека сборки. Если эта опция не указана, генерации разделяемой библиотеки сборки не производится.

N Не генерировать разделяемую библиотеку выполнения. Эта опция используется для того, чтобы создать только разделяемую библиотеку сборки. Тем не менее, следует обязательно указывать и опцию -t, так как для создания разделяемой библиотеки сборки требуется версия разделяемой библиотеки выполнения.

L каталог... Изменить алгоритм поиска для разделяемых библиотек сборки, указанных директивой #objects noload, так, что поиск вначале производится в указанном каталоге, а только потом в каталогах по умолчанию. Опция -L может быть указана в командной строке несколько раз, при этом каталоги просматриваются в указанном порядке перед поиском в каталогах по умолчанию.

Q Не выдавать предупреждающих сообщений. Эта опция используется, если известно, что будет выдано множество ненужных предупреждений.

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

Каждая директива, за которой может следовать несколько строк спецификаций, действует до тех пор, пока не закончится файл или не встретится другая директива. #address секция адрес Указывает начальный адрес секции разделяемой библиотеки выполнения. Эта директива обычно используется для задания начальных адресов секций.text и.data.

#target маршрутное_имя Задает маршрутное_имя разделяемой библиотеки выполнения во время ее использования. Указанное имя записывается в файлы типа a.out(4), обращающиеся к разделяемой библиотеке, и служит операционной системе для поиска разделяемой библиотеки, когда она требуется выполняемому файлу.

#branch Указывает на начало спецификаций таблицы переходов. Строки, следующие за этой директивой, трактуются как строки спецификации таблицы переходов. Строки спецификации таблицы переходов имеют следующий формат:

Имя_функции пробел_или_табуляция позиция где имя_функции - это имя, для которого задается точка входа в таблицу переходов, а позиция задает позицию этой точки входа. Позиция может быть целым числом или диапазоном целых чисел в формате позиция1-позиция2. Каждая позиция должна быть не меньше 1; одна и та же позиция не может быть указана дважды; в таблице переходов не должно быть пропущенных позиций (каждое число от 1 до некоторого максимального должно быть обязательно задействовано).

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

#objects Указывает имена об ектных модулей, составляющих разделяемую библиотеку выполнения. Строки, следующие за этой директивой, рассматриваются как список об ектных файлов, в том порядке, в котором они должны быть загружены в разделяемую библиотеку выполнения. Список состоит из имен файлов, разделяемых пробелами или табуляциями. Этот же список используется для определения об ектных файлов для разделяемой библиотеки сборки, но порядок их в разделяемой библиотеке сборки определяется пропуском списка через lorder(1) и tsort(1) . Эта директива может встретиться в файле спецификаций разделяемой библиотеки только однажды.

#objects noload За данной директивой следует список имен разделяемых библиотек сборки. Эти библиотеки просматриваются в том порядке, в котором они указаны, для разрешения ссылок из создаваемой разделяемой библиотеки. При этом ситуация, когда неразделяемая версия об екта обнаруживается раньше разделяемой, трактуется как ошибочная.

Имя разделяемой библиотеки сборки задается как маршрутное имя файла или как аргумент вида -lX, где libX.a является именем файла в каталоге LIBDIR или LLIBDIR. Описываемая ситуация аналогична ситуации с ld(1) , и для задания других каталогов поиска библиотек можно воспользоваться опцией -L.

Отметим, что если с помощью директивы #objects noload указана разделяемая библиотека сборки, то в каждой команде cc, редактирующей связи с создаваемой разделяемой библиотекой, нужно также задавать упомянутую разделяемую библиотеку сборки.

#hide linker [*] Эта директива делает внешние имена локальными для создаваемой разделяемой библиотеки. В последующих строках могут задаваться регулярные выражения [см. sh(1) , find(1) ], и если внешнее имя соответствует хотя бы одному из выражений, оно становится локальным. Оставить некоторые имена внешними можно с помощью директивы #export (см. ниже). Необязательный аргумент * эквивалентен последовательности

#hide linker * и приводит к тому, что все внешние имена становятся локальными.

Все имена, использованные в директивах #init и #branch, всегда являются внешними и не могут быть сделаны локальными с помощью директивы #hide.

#export linker [*] В последующих строках могут задаваться внешние имена, которые из-за соответствия регулярным выражениям директивы #hide могли бы стать локальными. Например, последовательность директив

#hide linker * #export linker one two приводит к тому, что все имена, кроме one и two, а также тех, которые упомянуты в директивах #init и #branch, становятся локальными.

#init об ектный_файл Указывает об ектный файл, который требует инициализации. Строки, следующие за этой директивой, рассматриваются как строки спецификации инициализации, которые должны иметь следующий формат:

Указатель пробел_или_табуляция имя где указатель - это указатель на внешнее имя; указатель должен быть определен в об ектном_файле. Для каждой такой строки генерируются команды инициализации вида: указатель=&имя; Повторная инициализация указателей не допускается, так же, как и повторное использование директивы #init для того же об ектного_файла.

#ident цепочка_символов Задает цепочку_символов, которая будет включена в секцию комментариев (.comment) разделяемой библиотеки выполнения.

## Комментарий. Строки, начинающиеся с ##, игнорируются.

ФАЙЛЫ

LIBDIR Обычно /lib. LLIBDIR Обычно /usr/lib. TMPDIR/* Временные файлы.

Обычно каталог TMPDIR - это /usr/tmp, однако данное соглашение можно изменить, присвоив переменной окружения TMPDIR другое значение [см. tempnam() в tmpnam(3S) ].

СМ. ТАКЖЕ
ar(1) , as(1) , cc(1) , ld(1) , lorder(1) , tsort(1) . a.out(4), ar(4) в Справочнике программиста.

ОГРАНИЧЕНИЯ
Опцию -n нельзя использовать одновременно с директивой #objects noload. Если указать разделяемую библиотеку сборки, которая уже существует, то mkshlib обновит ее с помощью команды ar -ru. Следовательно, если удаляется или переименовывается об ектный файл, включенный в разделяемую библиотеку сборки, то перед обновлением нужно обязательно удалить разделяемую библиотеку сборки.

Gcc -fPIC -c helloworld.c -o helloworld.o gcc -shared -Wl,-soname,libhelloworld.so.1 -o libhelloworld.so.1.0.1 helloworld.o

Первая команда компилирует исходник helloworld.c в объектный файл helloworld.o, вторая - создает из объектного файла разделяемую библиотеку helloworld.so.1.0.1. Следует обратить внимание на следующие вещи.

  • Объектники нужно компилировать с опцией -fPIC (position-independent code).
  • Линковать разделяемую библиотеку нужно, соответственно, с опцией -shared.
  • Опция -Wl позволяет задать опции для линковщика, в данном случае, soname.
  • soname - имя, которое известно программе, которая будет использовать библиотеку. Оно должно предваряться префиксом "lib", а заканчиваться ".so.X", где Х - номер версии, который изменяется когда изменяется интерфейс библиотеки.
  • Опция -o задает имя выходного файла, которое должно представлять собой soname дополненное через точку минорным номером версии (minor number) и номером релиза.
  • У всех разделяемых библиотек в Linux есть еще третье имя - имя, которое использует компилятор. Это soname без номера версии.

Как установить созданную библиотеку в Linux

Lib_name = libhelloworld.so.1 lib_full_name = libhelloworld.so.1.0.1 lib_short_name = libhelloworld.so lib_install_path = /usr/lib lib_include_path = /usr/local/include install: so sudo install -m 0644 $(lib_full_name) $(lib_install_path) sudo ln -sf $(lib_install_path)/$(lib_full_name) $(lib_install_path)/$(lib_short_name) sudo ldconfig -n $(lib_install_path) sudo cp helloworld.h $(lib_include_path) .PHONY: install

Этот фрагмент makefile добавляет цель install, то есть теперь можно выполнить команду make install и библиотека будет установлена в /usr/lib.

  • Команда "install" копирует заданный файл библиотеки по заданному пути и создает символьную ссылку на него с именем, заданным в soname. Опция -m позволяет задать также права доступа для файла (644 - разрешение на запись и чтение для владельца файла, чтение для пользователей той же группы, чтение для остальных пользователей).
  • Команда "sudo ln -sf" создает символьную ссылку с перезаписью существующей (если такая уже есть) на файл только что установлненой библиотеки с именем для компилятора (soname без версии). После этой команды в заданном каталоге присутствуют файлы библиотеки со всеми тремя ранее перечисленными именами.
  • Команда "sudo ldconfig -n" перечитывает заданный каталог (опция -n) и обновляет кэш. После этого линкер и другие программы могут запрашивать библиотеку по имени (например, по soname). Можно вывести список всехъ загруженных библиотек с помощью команды "ldconfig -p".
  • Далее в случае необходимости можно скопировать заголовочные файлы библиотеки.
  • Цель "install" должна создаваться как

Статические и динамические библиотеки.

Библиотеками называют «сборники» подпрограмм или объектов, как правило, ориентированных на решение набора близких по тематике задач. С точки зрения их организации и использования библиотеки бывают статическими и динамическими.

Статические библиотеки (static library) могут представлять собой набор исходных кодов, подключаемых программистом в свою программу, либо в виде заранее скомпилированных объектных файлов, связываемых вместе на этапе компиляции. В Windows такие файлы обычно имеют расширение <.lib>. В результате связывания со статической библиотекой, программа включает все используемые ей функции, что увеличивает её размер, но делает более автономной.

Динамические библиотеки (shared library, dynamic link library) загружаются операционной системой по «требованию» запущенной программы уже в ходе её выполнения. Если необходимая библиотека уже была загружена в память, то повторная загрузка не выполняется. При этом один и тот же набор функций или объектов библиотеки может быть использован одновременно несколькими работающими программами, что позволяет эффективно использовать ресурсы оперативной памяти. Динамические библиотеки в Windows обычно имеют расширение <.dll>.

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

Создание динамической библиотеки.

В Microsoft Visual Studio создание проекта для построения динамической библиотеки аналогично привычной процедуре создания проекта косольного приложения. Тип проекта Win32 Console Application, только теперь в мастере создания проекта нужно быдет выбрать пункт «DLL»:

В случае, если такой пункт в мастере отсутствует, можно создать обычный проект Console Application, а затем в свойствах проекта задать его тип:

Configuration Properties => General => Configuration Type: Dynamic Library (.dll)

Declspec(dllexport) void display(const char * str);

#include "dlltest.h"

void display(const char * str)

Модификатор __declspec(dllexport) разрешает экспорт библиотекой указанной функции для использования её другими приложениями.

В результате сборки проекта будет создан файл динамической библиотеки с расширением <.dll>, а также файл библиотеки импорта с расширением <.lib>. Библиотека импорта предназначена для облегчения последующего использования динамической библиотеки. Несмотря на то, что расширение файла библиотеки импорта совпадает со стандартным расширением статических библиотек, путать их не стоит.

Использование динамической библиотеки.

Использовать динамическую библиотеку в программе можно двумя способами. Неявное связывание подразумевает использование библиотеки импорта для определения адресов функций, предоставляемых библиотекой. Операционная система загружает библиотеку DLL после загрузки исполняемого файла программы. Исполняемый файл вызывает экспортированные функции библиотеки DLL таким способом, как если бы функции содержались в самом исполняемом файле.

При явном связывании исполняемый файл, использующий библиотеку DLL, должен делать вызовы функции для явной загрузки и выгрузки библиотеки DLL и осуществления доступа к экспортированным функциям библиотеки DLL. Клиентский исполняемый файл вызывает экспортированные функции с помощью указателя функции.

Независимо от выбранного метода исполняемый файл может использовать одну и туже библиотеку DLL. Более того, эти механизмы не являются взаимоисключающими, поскольку в то время как один исполняемый файл неявно связывается с библиотекой DLL, другой может выполнять явное связывание.

В качестве примера воспользуемся механизмом неявного связывания (как наиболее простого) для подключения построенной простой библиотеки.

Создадим отдельный проект обычного консольного приложения (можно в рамках того же решения, что и проект самой библиотеки). Для использования функции display, реализованной в библиотеке, необходимо:

    Подключить соответствующий заголовочный файл “dlltest.h”. Для этого нужно либо использовать путь к файлу непосредственно в директиве #include (если проекты находятся в одной папке решения, то лучше использовать относительный путь), либо в свойствах проекта добавить путь к этому заголовочному файлу в разделе

Configuration Parameters => C/C++ => General => Additional Include Directories

    Использовать файл соответствующей библиотеки импорта. Для этого можно воспользоваться директивой вида (здесь использован относительный путь к построенному lib-файлу).

Кроме того, можно добавить путь к файлу библиотеки импорта в свойствах проекта в разделе

Configuration Parameters => Linker => Input => Additional Dependencies

Теперь создадим основной файл программы с таким содержимым:

#pragma comment(lib, "../Debug/dlltest.lib")

#include "dlltest.h"

display("Hello");

system("pause");

Для успешного запуска программы осталось только обеспечить доступность соответствующей DLL библиотеки. При запуске программы операционная система будет искать все требуемые файлы библиотек в папке, откуда была запущена программа, а также в системных путях, определеннных переменной окружения PATH. Соответственно, DLL файл построенной библиотеки должен либо лежать в одной папке вместе с исполняемым файлом вызывающей программы, либо в одной из папок, определенных в PATH.

Разделяемая библиотека позволяет использовать содержащиеся в ней символы в нескольких фильмах без копирования этих символов в библиотеки фильмов. Из-за этого объекты разделяемой библиотеки называются ресурсами (Assets). При этом разделяемая библиотека используется как внешний файл и не добавляется к создаваемому (или редактируемому) фильму.

Применение разделяемых библиотек целесообразно, например, в следующих случаях:

  • при использовании одного и того же звукового сопровождения на нескольких страницах сайта;
  • при совместном использовании текстовых символов шрифта на нескольких страницах сайта;
  • когда требуется обеспечить единый источник для элементов анимации, используемой в нескольких сценах фильма или в нескольких фильмах;
  • когда требуется иметь центральную библиотеку ресурсов, чтобы упростить контроль за вносимыми изменениями.

Flash MX поддерживает два типа разделяемых библиотек:

  • Run-time - разделяемая библиотека времени выполнения; символы, входящие в такую библиотеку, доступны для совместного использования несколькими фильмами, однако редактироваться такие символы могут только непосредственно в фильме-источнике;
  • Author-time - библиотека, разделяемая на время разработки; символы, входящие в такую библиотеку, доступны для совместного использования несколькими фильмами, причем разрешается редактировать содержимое библиотеки в любом фильме-совладельце.

Чтобы ресурсы разделяемой библиотеки могли быть доступны в фильмах, размещенных на удаленном сайте, Flash-файл с этой библиотекой должен быть экспортирован в формат SWF и загружен на Web-сайт.

Замечание

В предыдущей версии Flash поддерживается только разделяемая библиотека времени выполнения.

Чтобы создать разделяемую библиотеку типа Run-time, необходимо:

  1. Определить ее ресурсы (входящие в нее символы) в отдельном фильме.
  2. Разрешить экспорт разделяемых символов.
  3. Указать URL сайта, на котором будет размещена библиотека.
  4. Экспортировать Flash-файл с этой библиотекой в формат SWF и выгрузить на Web-сайт.

Чтобы получить возможность использовать символы разделяемой библиотеки Run-time в других фильмах («совладельцах»), необходимо в каждом из них создать ссылку на разделяемые символы.

Теперь рассмотрим перечисленные выше шаги более подробно.

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

  1. Выберите в списке символ, который вы хотите сделать «разделяемым».
  2. В контекстном меню символа выберите команду Linking (Связывание).
  3. В открывшемся диалоговом окне Symbol Linkage Properties (Параметры связывания символа), рис. 10.12, установите флажок Export for runtime sharing (Разрешить экспорт на время выполнения).
  4. В текстовом поле Identifier введите имя (идентификатор) символа, под которым он будет экспортирован в фильм-совладелец; хотя по умолчанию в поле заносится библиотечное имя символа, если оно содержит пробелы, удалите их.
  5. В текстовом поле URL введите интернет-адрес фильма-источника (то есть SWF-файла с разделяемой библиотекой).
  6. Если экспортируемый символ следует использовать непосредственно с первого кадра фильма-совладельца, установите флажок Export in first frame.
  7. Если экспортируемый символ следует сделать доступным в сценарии на ActionScript, установите флажок Export for ActionScript.

Рис. 10.12. Диалоговое окно установки параметров символов разделяемой библиотеки

Чтобы использовать ресурсы разделяемой библиотеки Run-time в фильме-совладельце, требуется выполнить следующие действия:

  1. Откройте библиотеку этого фильма, выбрав в меню Window команду Library.
  2. В раскрывающемся меню библиотеки выберите команду New Symbol; в результате на экране появится диалоговое окно Create New Symbol (Создание нового символа), центральная часть которого аналогична по формату диалоговому окну Symbol Linkage Properties (рис. 10.13).
  3. В текстовом поле Identifier введите имя символа, который следует импортировать в фильм-совладелец.
  4. В текстовом поле URL введите интернет-адрес фильма-источника.

Рис. 10.13. Диалоговое окно для установки параметров разделяемого символа

Применение разделяемой библиотеки другого типа - Author-time - позволяет изменять (точнее, заменять) содержимое символов в редактируемом FLA-файле. При этом следует иметь в виду, что имя символа уже «зашито» в редактируемом фильме. Поэтому символ, импортируемый из разделяемой библиотеки, как бы подменяет собой исходный символ, сохраняя его имя. Если импортируемый символ содержит вложенные символы, они также будут импортированы.

Чтобы связать символ, подлежащий «подмене», с соответствующим символом из разделяемой библиотеки, необходимо:

  1. В редактируемом файле откройте окно библиотеки, выбрав в меню Window команду Library.
  2. В списке символов выберите символ, подлежащий «подмене», щелкните на нем правой кнопкой и в контекстном меню выберите команду Properties.
  3. В нижней части открывшегося диалогового окна. (см. рис. 10.13), в группе элементов Source (Источник) щелкните на кнопке Browse (Просмотр), и в окне Window Explorer выберите FLA-файл с нужной библиотекой; в результате на экране появится еще одно окно - Select Source Symbol (Выбор символа-источника), которое содержит список всех символов разделяемой библиотеки (рис. 10.14).


Рис. 10.14. Диалоговое окно Select Source Symbol

  1. Выберите в списке нужный символ и щелкните на кнопке ОК; это приведет к закрытию окна и изменению формата элементов управления в группе Source (рис. 10.15):
    • станет доступен флажок Always update before publishing (Всегда обновлять перед публикацией) - если он установлен, то символ в редактируемом фильме будет автоматически заменяться символом из разделяемой библиотеки при публикации фильма;
    • в текстовом поле File появится путь к файлу с разделяемой библиотекой;
    • в текстовом поле Symbol Name появится имя символа из разделяемой библиотеки;
    • станет доступна кнопка Symbol, щелчок на которой открывает диалоговое окно Select Source Symbol, приведенное на рис. 10.14.


Рис. 10.15. Формат элементов управления в группе Source после связывания символов

Замечание

Фильм может использовать ресурсы нескольких разделяемых библиотек любого типа.

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

  1. Выбрать в меню File (Файл) основного окна Flash команду Open As Library (Открыть как библиотеку).
  2. С помощью окна Windows Explorer указать Flash-файл с нужной библиотекой; в результате на столе будет открыто окно этой библиотеки.
  3. Скопировать нужные символы из окна библиотеки в библиотеку фильма (или непосредственно на стол).

Содержимое такой библиотеки, подобно содержимому общей и постоянной библиотек, не может быть изменено из фильма-клиента (то есть из фильма, использующего ее ресурсы).

Публикации по теме