Инициализация платформы во время выполнения

Когда платформа сначала загружается уникальным процессом, системные вызовы код инициализации платформы. До OS X v10.4, инициализация платформы обычно состояла из единственной подпрограммы, которую вызвали, когда была сначала загружена платформа; однако, в OS X v10.4 и позже, использование инициализаторов модуля и финализаторов стал предпочтительным методом. Основное преимущество инициализаторов модуля состоит в том, что их можно вызвать после того, как динамический компоновщик имеет возможность загрузить любые другие библиотеки, от которых зависит инициализатор модуля. То же не верно для подпрограмм инициализации платформы, которые сразу вызывают на загрузке и могут произойти, прежде чем другие важные модули (как время выполнения C++) загружаются.

Подпрограммы инициализации и производительность

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

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

Определение инициализаторов модуля и финализаторов

Инициализаторы модуля являются предпочтительным способом инициализировать платформу. Инициализатор модуля является статической функцией, не берущей параметров и не возвращающей значения. Это объявляется с помощью constructor атрибут компилятора как показано в Перечислении 1. Как с любой статической функцией инициализации, необходимо принять меры против функции, вызванной дважды путем размещения защитной переменной вокруг кода инициализации.

  Инициализатор Модуля перечисления 1 для платформы

__attribute__((constructor))
static void MyModuleInitializer()
{
    static initialized = 0;
    if (!initialized)
    {
        // Initialization code.
        initialized = 1;
    }
}

Платформы могут определить многократные функции инициализатора модуля. Редактор динамического канала вызывает любые функции инициализатора модуля после инициализации любых статических переменных, но прежде, чем вызвать любые другие функции или методы в Вашей платформе. Если код в функции инициализатора модуля полагается на другие библиотеки, такие как время выполнения C++, динамический компоновщик загружает те библиотеки до вызывания функции. Когда платформа загружается процессом, каждая функция инициализатора модуля вызвана только один раз. Инициализаторы модуля выполняются в порядке, с ними встречается компилятор.

Символы для любых функций инициализатора модуля не должны быть экспортированы Вашей платформой. По умолчанию XCode экспортирует все символы, объявленные в заголовочных файлах Вашего проекта. Можно ограничить набор экспортируемых символов путем явного экспорта списка символов или путем сокрытия определенных символов (и экспорта всего остального). Для получения информации о том, как сконфигурировать экспорт Вашей платформы, посмотрите Экспорт Вашего Интерфейса Платформы.

В OS X v10.4 и позже, инициализаторы модуля могут получить доступ к параметрам запуска за текущий процесс, как показано в Перечислении 2. Платформа могла бы использовать эти параметры для получения информации о конфигурации запуска приложения, такого как любые переменные окружения, или флаги передали в строке запуска.

  Инициализатор Модуля перечисления 2 с параметрами запуска

__attribute__((constructor))
static void initializer(int argc, char** argv, char** envp)
{
    // Initialization code.
}

В дополнение к функциям инициализатора модуля можно также определить функции финализатора модуля, реализующие, любой очищает код для платформы. Финализаторы модуля объявляются с помощью destructor атрибут компилятора как показано в Перечислении 3. Как инициализаторы модуля, символы для финализаторов модуля не должны быть экспортированы Вашей платформой. Финализаторы модуля выполняются в обратном порядке, что с ними встречается компилятор.

  Функция финализатора Модуля перечисления 3

__attribute__((destructor))
static void finalizer()
{
   // Clean up code.
}

Используя подпрограммы инициализации

Если Ваша платформа должна работать в версиях OS X до 10,4, можно все еще использовать функцию инициализации платформы по мере необходимости для инициализации структур данных платформы. При реализации подпрограммы инициализации, однако, важно выполнить как можно меньше работы. Поскольку Ваша подпрограмма инициализации сразу работает во время загрузки, другие модули кода не могут быть загружены и не доступны для использования, таким образом, важно, чтобы Вы не выполняли сложной инициализации, вовлекающей другие библиотеки.

Подпись функции инициализации совпадает с этим для стандартного инициализатора модуля:

void MyFrameworkInit()

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

  1. Выберите свою платформу, предназначаются и открывают окно инспектора.

  2. В области Build найдите установку сборки Подпрограммы Инициализации. Это с Соединением опций.

  3. Установите значение этой установки в имя символа Вашей подпрограммы инициализации.

Для ANSI подпрограммы на базе С имя символа является просто именем функции с символом начального символа подчеркивания. Например, имя символа для MyFrameworkInit функция _MyFrameworkInit. Вы не должны использовать подпрограммы C++ для функций инициализации.

При наличии затруднений при создании платформы с указанной подпрограммой инициализации существует несколько вещей, можно попытаться решить проблему. Используйте nm инструмент командной строки для подтверждения имени символа подпрограммы. Можно также использовать nm с -g опция удостовериться, что глобальный символ для Вашей подпрограммы экспортируется библиотекой. Если это не, проверьте, чтобы видеть, имеете ли Вы файл экспорта и удостоверяетесь, что Ваша подпрограмма включена в него.