May 3, 2011

Shared Library - An Introduction

A shared library is a library required by an executable to run properly. Such executables are called incomplete executables as they call routines present in the shared library code. The executables generated from the shared library are smaller in size than the ones generated from a static library

When an executable built with shared library is run, the dynamic loader identifies the list of dependent libraries to be loaded and searches for them in the standard default locations and the locations pointed to by the environment variable LD_LIBRARY_PATH (Linux), SHLIB_PATH (HP-UX), LIBPATH (AIX)

Shown below is the Employee class which we will use to generate the shared library libemployee.so

 1 #ifndef _Employee_H_
 2 #define _Employee_H_
 3 
 4 //File: Employee.h
 5 
 6 #include <iostream>
 7 
 8 class Employee
 9 {
10   public:
11       Employee();
12       Employee(const std::string name, int age);
13       virtual ~Employee();
14 
15       //Modifiers
16       void setName(const std::string name);
17       void setAge(int age);
18 
19       //Accessors
20       const char* getName() const;
21       int getAge()          const;
22 
23   private:
24       std::string m_name;
25       int m_age;
26 };
27 
28 #endif //_Employee_H_

 1 #include "Employee.h"
 2 //File: Employee.cpp
 3 
 4 Employee::Employee()
 5 {
 6 }
 7 
 8 Employee::Employee(const std::string name, int age)
 9 {
10     m_name = name;
11     m_age = age;
12 }
13 
14 Employee::~Employee()
15 {
16 }
17 
18 void Employee::setName(const std::string name)
19 {
20     m_name = name;
21 }
22 
23 void Employee::setAge(int age)
24 {
25     m_age = age;
26 }
27 
28 const char* Employee::getName() const
29 {
30     return m_name.c_str();
31 }
32 
33 int Employee::getAge() const
34 {
35     return m_age;
36 }

Compiling the Employee source files to object files
g++ -Wall -c -fPIC -O -I. -o Employee.o Employee.cpp

Linking the object files to generate the shared library libemployee.so
gcc -o libemployee.so Employee.o -shared -fPIC -Wl,-rpath,. -L. -lstdc++

The Client Program
 1 #include "Employee.h"
 2 #include <iostream>
 3 
 4 int main()
 5 {
 6     Employee *emp = new Employee("Pankaj", 26);
 7     std::cout << "Employee Name: " << emp->getName() << std::endl;
 8     std::cout << "Employee Age : " << emp->getAge() << std::endl;
 9     delete emp;
10     return 0;
11 }

Compiling the Client Program
g++ -Wall -c -fPIC -O -I. -o Client.o Client.cpp

Linking against the employee shared library and building the executable.
gcc -o client Client.o -fPIC -Wl,-rpath,. -L. -lstdc++ -lemployee

Note: the prefix lib and the suffix .so are not specified when the library is mentioned for linking

Running ldd against the executable gives the following result
$ ldd client 
 linux-vdso.so.1 =>  (0x00007ffffc743000)
 libstdc++.so.6 => /usr/lib64/libstdc++.so.6 (0x00007f6f16f22000)
 libemployee.so => not found
 libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x00007f6f16d0c000)
 libc.so.6 => /lib64/libc.so.6 (0x00007f6f1699f000)
 libm.so.6 => /lib64/libm.so.6 (0x00007f6f16748000)
 /lib64/ld-linux-x86-64.so.2 (0x00007f6f1722b000)

The presence of libemployee.so confirms that the executable has been linked with the library and will need the library to be present in the lib path directories for the successful run

No comments :

Post a Comment