fcppt 5.2.0
Freundlich's C++ toolkit
Loading...
Searching...
No Matches
fcppt.export

Description

Macros related to library visibility.

Introduction

When building a library, several platforms have different notions of library visibility that the library author has to consider. A symbol (like a function or global object) can be hidden in the library or it can be made public for other libraries or programs to use (for POSIX systems it is slightly more complex, but the two mentioned cases are the ones that really matter). Furthermore the library author has to specify whether a symbol is currently being exported or imported (because some platforms like Windows need this).

Note
Although every symbol can be made public under a POSIX system by default, this is still not recommended, because you have to specify the visibility for Windows anyway and libraries with only public symbols tend to have an unnecessarily large interface.

Defining library interfaces

Several macros are provided to make a symbol public. Because it is necessary to specify whether a symbol is currently imported or exported, some additional work needs to be done by the library author and the build system to ensure that this is always correctly specified. The common way to do this is to define some kind of macro when the library is being built, which means the symbols are currently exported. This macro will not be defined in all other cases, which means the symbols are currently imported.

In the following example the macro MYLIB_EXPORTS is defined by the build system if the library is currently being built. This macro is used to define MYLIB_SYMBOL to either FCPPT_SYMBOL_EXPORT or FCPPT_SYMBOL_IMPORT .

#include <fcppt/symbol/export.hpp>
#include <fcppt/symbol/import.hpp>
// MYLIB_EXPORTS should be defined by the build system when the library is
// beign built. If other code includes the library's header, the macro will not
// be defined.
#ifdef MYLIB_EXPORTS
#define MYLIB_SYMBOL FCPPT_SYMBOL_EXPORT
#else
#define MYLIB_SYMBOL FCPPT_SYMBOL_IMPORT
#endif

MYLIB_SYMBOL can then be used to export a function.

namespace mylib
{
// Conditionally export func
MYLIB_SYMBOL
void func();
}

The definition of the function doesn't need anything special.

void mylib::func() {}

Exporting a vtable of a class

If a class's vtable needs to be exported, a special macro FCPPT_SYMBOL_CLASS must be used. This macro doesn't need to change whether the vtable is currently imported or exported.

See also
FCPPT_SYMBOL_CLASS for a detailed explanation on when this is necessary.
#include <fcppt/symbol/class.hpp>
namespace mylib
{
// Export the vtable of someclass
// NOLINTNEXTLINE(cppcoreguidelines-special-member-functions,hicpp-special-member-functions)
class FCPPT_SYMBOL_CLASS someclass
{
public:
// Also export its destructor
MYLIB_SYMBOL
virtual ~someclass();
};
}

List of things to export

Generally, every object with external linkage must be exported. This includes:

  • Functions (free or in a class), constructors and destructors which are defined inside the library need a conditional symbol like MYLIB_SYMBOL at their declaration, and nothing special at their definition.

  • Objects with external linkage defined inside the library are handled like functions.

    namespace mylib
    {
    MYLIB_SYMBOL
    extern const int some_constant;
    }
    int const mylib::some_constant = 42;

  • Classes that need their vtables to be exported must use FCPPT_SYMBOL_CLASS at their definition.

    See also
    Exporting a vtable of a class.
  • An explicitly instantiated template function needs everything that a normal function would need, but is also needs an FCPPT_SYMBOL_EXPORT_FUNCTION_INSTANTIATION at its explicit instantiation.

    In the following example, a templated function is explicitly instantiated and exported. The function declaration needs a conditional symbol like MYLIB_SYMBOL because a normal function would also need it.

    namespace mylib
    {
    template <typename T>
    MYLIB_SYMBOL void template_function(T const &);
    }

    The explicit instantiation needs an additional FCPPT_SYMBOL_EXPORT_FUNCTION_INSTANTIATION. It is important that this comes after the template keyword but before the rest of the explicit function instantiation.

    // Define our template function
    template <typename T>
    void mylib::template_function(T const &)
    {
    }
    // Explicitly instantiate the template function with int and export it
    #include <fcppt/symbol/export_function_instantiation.hpp>
    template FCPPT_SYMBOL_EXPORT_FUNCTION_INSTANTIATION void mylib::template_function<int>(int const &);

  • An explicitly instantiated template class is handled in a similarly to explicitly instantiated functions.

    In the following example, a templated class is explicitly instantiated and exported. The class definition is, again, as if it was a normal class.

    namespace mylib
    {
    template <typename T>
    class template_class
    {
    public:
    MYLIB_SYMBOL
    void some_function();
    };
    }

    The explicit instantiation needs an additional FCPPT_SYMBOL_EXPORT_CLASS_INSTANTIATION. It must be placed after the class or struct keyword and before the rest of the type.

    Warning
    If you fail to put the macro at the right place, some compilers may ignore the visibility attributes without any warnings.
    // Define the member functions of the template class
    template <typename T>
    void mylib::template_class<T>::some_function()
    {
    }
    // Explicitly instantiate the template class with int and export it
    #include <fcppt/symbol/export_class_instantiation.hpp>
    template class FCPPT_SYMBOL_EXPORT_CLASS_INSTANTIATION mylib::template_class<int>;

Compiler specific usage

Library visibility is only useful if a shared library is being built and if the symbols of the shared library are hidden by default. Here is some advice how to use different build systems:

  • For gcc and clang, you should use the option -fvisibility=hidden. Only then will all the symbols be hidden by default, so that making symbols public actually does anything.

  • gcc might ignore FCPPT_SYMBOL_EXPORT_FUNCTION_INSTANTIATION or FCPPT_SYMBOL_EXPORT_CLASS_INSTANTIATION if an implicit instantiation of the same type already took place in the same translation unit. You must ensure that this does not happen by creating separate translation units for every type you wish to explicitly instantiate and export.

Static linking

For static linking to work, all of the attributes must be disabled. To do that, we are first going to introduce a macro MYLIB_STATIC that is defined both when the static library is being built and when the library should be used statically.

#include <fcppt/symbol/export.hpp>
#include <fcppt/symbol/import.hpp>
// If MYLIB_STATIC is defined, the library is being built or used as a static
// library. In this case we can't use any special symbols.
#ifdef MYLIB_STATIC
#define MYLIB_SYMBOL
#elifdef MYLIB_EXPORTS
#define MYLIB_SYMBOL FCPPT_SYMBOL_EXPORT
#else
#define MYLIB_SYMBOL FCPPT_SYMBOL_IMPORT
#endif

You also have to make sure that the macros for explicit template instantiations are empty if MYLIB_STATIC is defined. These two macros should be used instead of the ones provided by fcppt.

#include <fcppt/symbol/export_class_instantiation.hpp>
#include <fcppt/symbol/export_function_instantiation.hpp>
// Also, we have to leave the macros for explicit instantiations empty, if
// MYLIB_STATIC is defined.
#ifdef MYLIB_STATIC
#define MYLIB_EXPORT_CLASS_INSTANTIATION
#define MYLIB_EXPORT_FUNCTION_INSTANTIATION
#else
#define MYLIB_EXPORT_CLASS_INSTANTIATION FCPPT_SYMBOL_EXPORT_CLASS_INSTANTIATION
#define MYLIB_EXPORT_FUNCTION_INSTANTIATION FCPPT_SYMBOL_EXPORT_FUNCTION_INSTANTIATION
#endif

Header files

Header fileDescription
symbol/export.hppContains FCPPT_SYMBOL_EXPORT .
symbol/import.hppContains FCPPT_SYMBOL_IMPORT .
symbol/class.hppContains FCPPT_SYMBOL_CLASS .
symbol/export_class_instantiation.hppContains FCPPT_SYMBOL_EXPORT_CLASS_INSTANTIATION .
symbol/export_function_instantiation.hppContains FCPPT_SYMBOL_EXPORT_FUNCTION_INSTANTIATION .

Macros

#define FCPPT_SYMBOL_CLASS   FCPPT_SYMBOL_CLASS_IMPL
 Tells that a classes's vtable should be exported.
#define FCPPT_SYMBOL_EXPORT   FCPPT_SYMBOL_EXPORT_IMPL
 Tells that a symbol should be exported.
#define FCPPT_SYMBOL_EXPORT_CLASS_INSTANTIATION   FCPPT_SYMBOL_EXPORT_CLASS_INSTANTIATION_IMPL
 Tells that an explicit class instantiation should be exported.
#define FCPPT_SYMBOL_EXPORT_FUNCTION_INSTANTIATION   FCPPT_SYMBOL_EXPORT
 Tells that an explicit function instantiation should be exported.
#define FCPPT_SYMBOL_IMPORT   FCPPT_SYMBOL_IMPORT_IMPL
 Tells that a symbol should be imported.

Macro Definition Documentation

◆ FCPPT_SYMBOL_CLASS

#define FCPPT_SYMBOL_CLASS   FCPPT_SYMBOL_CLASS_IMPL

Tells that a classes's vtable should be exported.

This macro marks a classes's vtable to be exported, so it can be shared across dynamic libraries. There are several cases in which this is necessary:

  • The class is thrown as an exception and caught by another library.

  • The class has virtual methods that will be called directly from another library.

It is not necessary to specify whether the class is currently exported or imported.

class FCPPT_DETAIL_SYMBOL_CLASS my_exception
{
};
class FCPPT_DETAIL_SYMBOL_CLASS my_base
{
virtual
void
do_something() = 0;
};
See also
Exporting a vtable of a class

◆ FCPPT_SYMBOL_EXPORT

#define FCPPT_SYMBOL_EXPORT   FCPPT_SYMBOL_EXPORT_IMPL

Tells that a symbol should be exported.

This macro marks a symbol to be exported, so it can be used by other libraries or programs.

See also
Defining library interfaces

◆ FCPPT_SYMBOL_EXPORT_CLASS_INSTANTIATION

#define FCPPT_SYMBOL_EXPORT_CLASS_INSTANTIATION   FCPPT_SYMBOL_EXPORT_CLASS_INSTANTIATION_IMPL

Tells that an explicit class instantiation should be exported.

This macro marks an explicitly instantiated template class to be exported, so it can be used by other libraries or programs.

See also
Defining library interfaces

◆ FCPPT_SYMBOL_EXPORT_FUNCTION_INSTANTIATION

#define FCPPT_SYMBOL_EXPORT_FUNCTION_INSTANTIATION   FCPPT_SYMBOL_EXPORT

Tells that an explicit function instantiation should be exported.

This macro marks an explicitly instantiated template function to be exported, so it can be used by other libraries or programs.

See also
Defining library interfaces

◆ FCPPT_SYMBOL_IMPORT

#define FCPPT_SYMBOL_IMPORT   FCPPT_SYMBOL_IMPORT_IMPL

Tells that a symbol should be imported.

This macro marks a symbol to be imported, so it can be used from another library.

See also
Defining library interfaces