Shared Object Libraries For Mac
December 06, 2014 topic: tagged:. If you want to make your C/C project portable between operating systems and compilers, there are some things to consider. In this article I focus on shared libraries and give a practical overview on how to create and use shared libraries with various compilers on various operating systems, with the goal of portable source code and a unified build process. “A shared library or shared object is a file that is shared by executable files and further shared objects files.” A shared library on Linux is called “ dynamically linked shared object”, and has the file extension.so. The windows equivalent is the “ dynamic link library” usually with file extension.dll. This article is structured as follows: At first we create and use a minimal shared library on Linux with GCC.

We take a look at the necessary gcc options for compiling and linking and check at the exported symbols of the.so file with the tool “nm”. Then we build the same code on Windows with MinGW. At first by directly linking the dynamic link library. Then, we also build and use a so-called import library - we have to consider some platform/compiler specifics at this point. I give a brief explanation what an import library is and when it ’s needed. We go on by building our minimal demo application with other compilers, like the Microsoft Visual C Compiler (MSVC).
To make the build process more convenient and more flexible, we use CMake at this point. Last but not least, a few words about the interoperability of libraries created with different compilers (ABI compatibility) follow.
The final version of the minimalistic portable code demo, that is gradually developed in this post, is available on. Shared libraries with Linux/GCC Let’s start building our demo on Linux with GCC. The header of our shared library is shared.h and its implementation is in shared.cpp. Our application is implemented in main.cpp, where we want to use our shared library: shared.h.
$./main./main: error while loading shared libraries: libshared.so: cannot open shared object file: No such file or directory To solve this problem, we must somehow specify where the library can be found. On Linux, the environment variable LDLIBRARYPATH can be used to specify directories where libraries are searched for first (before the standard set of directories)() = prepending our commands above with LDLIBRARYPATH=./ solves the issue of the not found library and the program will execute like expected. $ LDLIBRARYPATH =./main f X::X X::mX Shared libraries with Windows/MinGW To be able to compile/link our code with different compilers, we have to consider some compiler specifics.
MSVC cannot directly link to a dll - we need a so-called “import library”. Symbol Visibility: GCC/MinGW exports all symbols by default, MSVC exports no symbol by default. Linking the DLL directly If you are on Windows and compile everything with MinGW (the DLL and the application), linking directly to the dll is fine. You can take the source code from above without any changes and build it very similar like on Linux. G -fPIC -shared -o shared.dll shared.cpp g -L.lshared -o main main.cpp The above lines produce shared.dll and main.exe that links directly against shared.dll. Creating and linking the import library Like shown above, it is perfectly fine to directly link the DLL if the DLL was also created by MinGW.
But this is not the common way to work with shared libraries on windows because just a few compilers support this - the Microsoft Visual Studio Compiler is not among them. On Windows, a DLL usually has a matching so called “import library”. If an executable wants to use functions of a DLL it does not link the DLL directly but it’s import library. Import libraries are similar to static libraries and usually also have a.lib file ending. In contrast to static libraries, they do not contain the complete function definitions, but just “stubs” of the exported symbols of the DLL to satisfy the linker and to load the DLL at runtime.
We can create the DLL and its corresponding import library with MinGW(). G -o main.exe main.o -L.llibshareddll Symbol visibility The default behavior of MinGW is to export ALL symbols of a DLL. But if one or more functions are declared with declspec(dllexport), only those functions are exported. The behavior of the Microsoft Visual Studio Compiler is different: Per default NO symbols are exported, just symbols explicitly declared with declspec(dllexport).
So let’s make the code “MSVC compatible”, without loosing the compatibility to the other compilers: We add an additional file sharedEXPORTS.h. G -DsharedEXPORTS -c shared.cpp g -shared -o shared.dll shared.o -Wl,-out-implib,libshareddll.lib g -o main.exe main.o -L.llibshareddll When using the library (i.e. Linking it to main.exe), sharedEXPORTS is not defined, and SHAREDEXPORT is set to declspec(dllimport). This means when we build the library, our functions are exported and when we want to use our library, the functions are imported from the dll. Creating shared libraries with CMake Up to now, we can build the same source code on Linux with GCC and on Windows with MinGW.

We also prepared the code to be compilable with the Microsoft Visual Studio Compiler (MSVC). Now we also want to build and use a DLL with other compilers like MSVC.
Therefore we don’t create the in Visual Studio solution by hand, instead we choose a more flexible method and use. Is a cross-platform build tool that tremendously simplifies building C/C code with different compilers on different platforms. With just a few steps we can build our code without having to worry about the exact compilation/linking steps. If you don’t know CMake, I’ll highly recommend you to check it out. This is no CMake tutorial, I’ll just show the general procedure:. At first we create generic project description in a more or less “declarative”, compiler and platform independent way. Therefore we create a file “CMakeLists.txt” in the source root folder with a just few lines (see below).
Then, we run “cmake” on the platform where we want to build. This generates a platform and compiler specific, “native” build description (e.g. Makefiles, a Visual Studio Solution or others) from the generic CMakeLists.txt. To actually build the code, we have to invoke the “native build command”, e.g. “make” if we use Makefiles. Ad 1.) The “generic project description” in CMakeLists.txt.
Export CXX =/usr/bin/clang export CC =/usr/bin/clang cmake -G 'Ninja' ninja Interoperability of Libraries (ABI compatibility) Libraries written in C, compiled with different compilers, or even just with different releases of the same compiler, often cannot be linked together. Sometimes there exists basic ABI (Application Binary Interface) compatibility (e.g. GCC and clang) but it’s likely that you have to recompile your library and your application from source with the same compiler to be able to link them.
Shared Object Libraries For Mac Windows 10
DLLs are slightly different: If the DLL is written in C it can be linked even with applications written in C. DLLs written in C work too, as long as you expose its symbols through a C interface declared with extern 'C'. Extern “C” makes a function-name in C have ‘C’ linkage and no compiler specific name mangling is applied.
Error While Loading Shared Libraries
For C classes this means you have to make some kind of “C wrapper” and expose those functions declared with extern 'C'. If you try to use the C interface of a library compiled with a different compiler you will likely get linker errors because different compilers often use incompatible name mangling schemes of the exported C symbols (the exported symbols are named differently).
For our demo shared library from above this means: We cannot build our demo with MinGW and link it to our application “main” built with MSVC. But we can easily declare our C function f with extern 'C'. This would allow us to use function f of the DLL even in applications build with different compilers. Extern 'C' void SHAREDEXPORT f.
To also make the functionality of class X available to be used by other compilers (e.g. You want to distribute the library in binary form), the most robust way would be to create a C wrapper: wrap the methods into C functions, and declare them as extern 'C'. There are also other techniques to create a binary compatible C interface (at least to a certain degree) - if you are interested in how this can be done, I suggest you to read. Of course there is no ABI compatibility between libraries/applications compiled on different operating systems unless you cross compile - but that’s another topic. The final version of the minimalistic portable code demo, that is gradually developed in this post, is available on.
If you have questions or any kind of feedback please leave a comment below.