.. _visibility: ***************** Symbol visibility ***************** .. highlight:: c :: #include When writing a shared library, you should always be careful to explicitly mark which functions and other symbols are part of the library's public API, and which should only be used internally by the library. There are a number of benefits to doing this; there is a good summary on the `GCC wiki`_. (Note that even though that summary is on the GCC wiki, the notes apply equally well to other compilers and platforms.) .. _GCC wiki: http://gcc.gnu.org/wiki/Visibility libcork provides several helper macros that make it easier to do this. We use these macros ourselves to define libcork's public API. Defining a library's public API ------------------------------- On some platforms (for instance, on Windows), you must declare each public function and symbol differently depending on whether you're compiling the library that *defines* the symbol, or a library or program that *uses* the symbol. The first is called an *export*, the second an *import*. On other platforms (for instance, GCC on Linux), the declaration of a public symbol is the same regardless of whether you're exporting or importing the symbol. libcork provides macros that let you explicitly declare a symbol as an export or an import in a platform-independent way. .. macro:: CORK_EXPORT CORK_IMPORT Explicitly declare that a symbol should be exported from the current shared library, or imported from some other shared library. However, you will rarely need to use these macros directly. Instead, when writing a new shared library, you should declare a new preprocessor macro (specific to the new library), which you'll use when declaring the library's public API. For instance, if you're creating a new library called *libfoo*, you would declare a new preprocessor macro called ``FOO_API``:: #if !defined(FOO_API) #define FOO_API CORK_IMPORT #endif This ensures that anyone who wants to *use* libfoo doesn't need to do anything special; the ``FOO_API`` macro will default to importing the symbols from libfoo's public API. When *building* libfoo, you must set up your build system to define this variable differently; since you need to *export* the symbols in this case, the ``FOO_API`` macro should be set to ``CORK_EXPORT``. Each build system will have a different way to do this. In CMake, for instance, you'd add the following: .. code-block:: cmake set_target_properties(libfoo PROPERTIES COMPILE_DEFINITIONS FOO_API=CORK_EXPORT ) Then, in all of your header files, you should use your new ``FOO_API`` macro when declaring each function or symbol in the public API:: FOO_API int foo_load_from_file(const char *name); FOO_API void foo_do_something_great(int flags); extern FOO_API const char *foo_name; Local symbols ------------- Normally, if you need a function to be local, and not be exported as part of the library's public API, you can just declare it ``static``:: static int file_local_function(void) { /* This function is not visible outside of this file. */ return 0; } This works great as long as the function is only needed within the current source file. Sometimes, though, you need to define a function that can be used in other source files within the same library, but which shouldn't be visible outside of the library. To do this, you should define the function using the :c:macro:`CORK_LOCAL` macro. .. macro:: CORK_LOCAL Declare a symbol that should be visible in any source file within the current library, but not visible outside of the library. As an example:: CORK_LOCAL int library_local_function(void) { /* This function is visible in other files, but not outside of the * library. */ return 0; } Since you're going to use this function in multiple files, you'll want to declare the function in a header file. However, since the function is not part of the public API, this should *not* be defined in a public header file (that is, one that's installed along with the shared library). Instead, you should include a private header file that's only available in your library's source code archive, and which should not be installed with the other public header files.