Compiling C++ Codes into shared library and linking them
Let's say you have files print.h and print.cpp, shown below that contains C++ codes you wish to compile as .so (shared object) file and they are stored in ~/demo/lib folder.
#ifndef __PRINT__
#define __PRINT__
#include <iostream>
#include <stdio.h>
void print(const char* p, bool endl = true);
#endif
#include <print.h>
void print(const char* p, bool endl)
{
std::cout << "print: " << p;
if (endl) std::cout << std::endl;
}
You can compile the above code into .o (static library) file with the command
~/demo/g++ -o lib.o -c ./lib/print.cpp
But we want to compile it as .so (shared library) file so we use the command instead
~/demo/g++ -o ./lib/liblib.so -shared -fpic ./lib/print.cpp
Note that with the above commands, liblib.so and lib.o is created in ~/demo/lib folder upon successful compilation.
Now let's say you have another set of C++ files loop.cpp and loop.h, shown below and you wish to compile them together with another C++ file into an .so file...
#ifndef __LOOP__
#define __LOOP__
#include <iostream>
#include <unistd.h>
class loop
{
public:
loop()
{
std::cout << "loop constructor"<< std::endl;
}
virtual ~loop()
{
std::cout << "loop destructor"<< std::endl;
}
void run(int i, int r);
};
#endif
#include <loop.h>
void loop::run(int i, int r)
{
while(r)
{
sleep(i);
std::cout << "loop..." << std::endl;
r--;
}
}
To compile print.cpp and loop.cpp files into a single .so file, do the command as shown below
~/demo/g++ -o ./lib/liblib.so -shared -fpic ./lib/print.cpp ./lib/loop.cpp
Now that we have .so file already, let's create a C++ program that will use this shared library and use the function and class it contains.
The C++ file below will be our C++ program. It is stored as main.cpp in ~/demo folder.
It uses print() from print.cpp to print "hello world" and uses loop class to perform a loop of 5 intervals.
#include <iostream>
#include <print.h>
#include <loop.h>
int main()
{
print("hello world");
loop p;
p.run(1,5);
return 0;
}
Let's compile this code and link the shared library with it. The command below shows how to compile it into "run".
g++ -o run main.cpp -L/lib -llib -I./lib -I./
If compile is successful, and executable named 'run' should appear in ~/demo folder. If you execute it, you might encounter an error as shown below. This is because when executing a program that has dependency on a shared library, it needs to know where the library is.
run: error while loading shared libraries: liblib.so: cannot open shared object file: No such file or directory
To fix this, you can do either of the two possible solutions
1. Copy the liblib.so into any folder listed in the system's LD_LIBRARY_PATH environment variable. This is a more consistent solution because you only do this once.
2. add ~/demo/lib folder into LD_LIBRARY_PATH environment variable. You have to keep setting this every time you try to execute your program in a new terminal. To do this, follow the command below:
~/setenv LD_LIBRARY_PATH ~/demo/lib:${LD_LIBRARY_PATH}
Now try to run the program again.
Using Makefile
You can create a makefile to simplify this process. Copy the code below into ~/demo/makefile
all: so main
so : ./lib/print.cpp ./lib/loop.cpp
g++ -o ./lib/liblib.so -shared -fpic ./lib/print.cpp ./lib/loop.cpp -I./lib
main : ./lib/liblib.so
g++ -o run main.cpp -L./lib -llib -I./lib -I ./
Then just call 'make' and the whole compiling process will be done.
Linking the Shared Library (.so) in Unison
In this guide, we will link a share library (.so) in a Unison test program and use the functions and classes defined in the shared library.
1. Optional: copy the .so file as well as its .h header files into test program folder
2. After loading test program, open TestTool
3. In the TestTool, select the application library you want to link the .so file. double-click it to open its settings. Below shows that I selected ST_DLOG application library from my test program.
4. Click on "Compiler and Linker" tab. Click the "Add Path.." button and select the path where the .so file is located.
5. Once done, you will see the path in the "Linker Paths" list box.
6. In the "Linker Flags" list box, click an empty row. then type -L<.so path> -l<.so name w/o lib prefix>. The -l flag lets me specify the filename of the .so file I want to use, but I without the 'lib' prefix and .so extension. My .so file's filename is liblib.so so removing the prefix and extension, it becomes -llib.
7. Click "Include Paths" tab.
8. Click the "Add Path.." button and select the path where the .h file is selected. Once done, you will see the path in the "Include Paths" list box.
9. Add the include file in the application library's source code. Below shows I declared the include on ST_Datalog.cpp. I included the 2 header files from my shared library - loop.h and print.h
10. Somewhere in ST_Datalog.cpp, i called mydemo::print() function which is defined in the shared library.
11. Finally, compile your application library.