Thursday, November 1, 2018

Compiling C++ Codes into shared Library and Linking Them


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.








No comments:

Post a Comment