Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

Design Rationale

ABI portability across compilers
User's plugin API
Performance and memory allocations
Self loading
Aliases vs Mangling

During discussion of the library a lot of questions were about ABI stability and should the library take care about it. It was decided that making ABI stable could be a useful feature, but it will add a lot of overhead and make the library usage less simple. For those who do not require ABI stability across compilers such feature will be an overkill.

It was decided to make this library more simple and low level, so that it could be used to make ABI stable plugins system for users that require it still not adding overhead for other users.

There are some open C++ plugin systems. Most of them force user to have some predefined API. The problem is that all of those API differ.

To be more usable Boost.DLL does not force API. It's up to user to design suitable API.

Some methods of the library use boost::filesystem::path or return std::vector<std::string>. This may look non optimal at first, but there is a reason to do so.

boost::filesystem::path allows to transparently use Unicode strings with non-Unicode ones. Using it provides a more user-friendly interface for the library while the performance overhead is not noticeable because of a slow file system operations that occur in boost::filesystem::path accepting methods.

std::vector<std::string> variables are returned by the library_info methods. Querying a library is a slow procedure anyway: it randomly reads parts of file from disc and executes algorithms that sometimes have linear complexity from sections or exported symbols count. Returning std::vector<std::string> simplifies implementation and does not require from user to keep an instance of library_info after query. Having not a very noticeable performance overhead in rarely called methods seems reasonable.

Other methods are assumed to be hot paths and optimized as much as possible.

There is a good big reason to make self loading via shared_library(program_location()) instead of having some shared_library::load_self() member method. That reason is the requirement to have an ability to call shared_library(this_line_location()) from any place, even from the main binary. We need that to link plugins into the binary and to create a transparent reference counting mechanism.

Making multiple interfaces that do exactly the same things looks unreasonable to me, that's why shared_library(program_location()) and shared_library(this_line_location()) are used without shared_library::load_self().

Mangling depends on source code, for example "boost::foo" could be foo function or foo variable. Depending on that knowledge it must be mangled in different ways. More problems arise if foo is an overloaded function that accepts parameters: "boost::foo(variant<int, short>)". In that case full name of parameter must be specified, which could be boost::variant<int, short> or variant<int, short, void_, void_> ...

There was an idea to allow user to forward declare function and generate mangled name from it:

namespace boost { void foo(variant<int, short>); }

std::string mangled_name = boost::dll::magic_mangle(boost::foo);

But that idea has epic failed because of linker problems and no reliable way to get mangled symbol name from compiler internals at compile time.

That's why aliases were considered a lesser evil:

BOOST_DLL_ALIAS(boost::foo, foo_variant) // in plugin
"foo_variant" // in plugin importer


PrevUpHomeNext