Во время обсуждения в библиотеке было много вопросов о стабильности АБИ, и библиотека должна позаботиться об этом. Было решено, что стабилизация ABI может быть полезной функцией, но она добавит много накладных расходов и сделает использование библиотеки менее простым. Для тех, кому не нужна стабильность ABI в компиляторах, такая функция будет перебором.
Было решено сделать эту библиотеку более простой и низкоуровневой, чтобы ее можно было использовать для создания стабильной системы плагинов ABI для пользователей, которые требуют, чтобы она все еще не добавляла накладные расходы для других пользователей.
Есть несколько открытых систем плагинов C++. Большинство из них вынуждают пользователя иметь определенный API. Проблема в том, что все эти API отличаются.
Чтобы быть более пригодным для использования. DLL не использует API. Пользователь должен разработать подходящий API.
Некоторые методы библиотеки используют<boost::filesystem::path
>или возвращают<std::vector<std::string>
>. На первый взгляд это может показаться не оптимальным, но есть причина для этого.
<boost::filesystem::path
>позволяет прозрачно использовать строки Unicode с не-Unicode. Использование его обеспечивает более удобный интерфейс для библиотеки, в то время как накладные расходы на производительность не заметны из-за медленных операций файловой системы, которые происходят в<boost::filesystem::path
>приемных методах.
<std::vector<std::string>
>переменные возвращаются методами<library_info
>. Запрос библиотеки - это медленная процедура: она случайно считывает части файла с диска и выполняет алгоритмы, которые иногда имеют линейную сложность из секций или количества экспортируемых символов. Возвращение<std::vector<std::string>
>упрощает реализацию и не требует от пользователя сохранения экземпляра<library_info
>после запроса. Не очень заметная производительность в редко называемых методах кажется разумной.
Другие методы считаются горячими и максимально оптимизированными.
Существует большая причина для самостоятельной загрузки<shared_library(program_location())
>вместо того, чтобы использовать метод<shared_library::load_self()
>. Эта причина — требование иметь возможность звонить<shared_library(this_line_location())
>из любого места, даже из основной двоичной системы. Нам нужно связать плагины с бинарными и создать прозрачный механизм подсчета ссылок.
Создание нескольких интерфейсов, которые делают одни и те же вещи, кажется мне необоснованным, поэтому<shared_library(program_location())
>и<shared_library(this_line_location())
>используются без<shared_library::load_self()
>.
Манглирование зависит от исходного кода, например<"boost::foo"
>может быть<foo
>функцией или<foo
>переменной. В зависимости от этого знания оно должно быть искажено по-разному. Больше проблем возникает, если<foo
>является перегруженной функцией, принимающей параметры:<"boost::foo(variant<int,
short>)"
>. В этом случае необходимо указать полное наименование параметра, которое может быть<boost::variant<int,
short>
>или<variant<int,short,void_,void_>
>.
Идея заключалась в том, чтобы позволить пользователю пересылать функцию декларирования и генерировать из нее искаженное имя:
namespace boost { void foo(variant<int, short>); }
std::string mangled_name = boost::dll::magic_mangle(boost::foo);
Но эта идея потерпела неудачу из-за проблем с линкером и отсутствия надежного способа получить испорченное имя символа из внутренних компонентов компилятора во время компиляции.
Вот почему псевдонимы считались меньшим злом:
BOOST_DLL_ALIAS(boost::foo, foo_variant)
"foo_variant"