Creating static and shared libraries


Back to Articles


more info http://tldp.org/HOWTO/Program-Library-HOWTO/static-libraries.html

Creating Static Libraries : Linux

We have 4 files with us

  • fun1.c => it store code of “add” and “sub” function
  • fun2.c => it store code of “mul” and “div” function
  • header.h => it store prototype of “add” , “sub” ,“mul” ,” div” function
  • user_pro.c =>user program that calls the function.

We have some intermediate files

  • fun1.o : object code for fun1.c
  • fun2.o : object code for fun2.c
  • mylib_sta.a : static library made by combining both object file
  • user_pro.o : object code for user_pro.c


We have final executable file user_pro_final

Coding of each files

  • fun1.c
int add (int a , int b){return a+b;}
int sum (int a , int b){return a-b;}
  • fun2.c
int mul (int a , int b){return a*b;}
float div (int a , int b){return ((float)a)/b;}
  • header.h
int add (int a , int b);
int sub (int a , int b);
int mul (int a , int b);
float div (int a , int b);
  • user_pro.c
#include"header.h"
#include
main()
{
int a,b;
printf("Enter a: ");
scanf("%d",&a);
printf("Enter b: ");
scanf("%d",&b);
printf("\naddition of a and b is %d: ",add(a,b));
printf("\nsutraction of a and b is %d: ",sub(a,b));
printf("\nmultiplication of a and b is %d: ",mul(a,b));
printf("\ndivide of a and b is %f: ",div(a,b));
return 0;
}
  • apply this procedure check the pwd
$ pwd
/home/student/Narendra/static
  • step 1 : create object code for all three .c file
$ gcc -c fun1.c fun2.c user_pro.c
$ ls *.o
fun1.o fun2.o user_pro.o
  • step 2 : create static named mylib_sta.a library from fun1.o and fun2.o
$ ar rcv mylib_sta.a fun1.o fun2.o
a - fun1.o
a - fun2.o
  • step 3 : create executable file named user_pro_final
$ gcc -o user_pro_final user_pro.o mylib_sta.a
  • step 4 : execute the user_pro_final
$ ./user_pro_final
Enter a: 45
Enter b: 12
addition of a and b is 57:
subtraction of a and b is 33:
multiplication of a and b is 540:
dividing of a and b is 3.750000:

Creating Shared Libraries : Linux

1. Load time Linking

we will work with some files from previous namely fun1.c fun2.c user_pro.c . but we will produce mylib_shr.a this time

  • path

$ pwd
/home/student/Narendra/shared
  • step 1 : create object code of all .c files
$ cc -Wall -fPIC -c fun1.c fun2.c user_pro.c
$ ls *.o
fun1.o fun2.o user_pro.o
  • step 2 : create shared library with fun1.o and fun2.o
$ cc -shared fun1.o fun2.o
$ mv a.out mylib_shr.so
  • step 3 : linking of shared lib to user code to produce user_pro_final again
$ cc user_pro.o -L. mylib_shr.so -o user_pro_final
  • step 4 : load library path
$ LD_LIBRARY_PATH=/home/student/Narendra/shared
$ export LD_LIBRARY_PATH
  • step 5 : run the executable file
$ ./user_pro_final_exe
Enter a: 45
Enter b: 12
addition of a and b is 57:
subtraction of a and b is 33:
multiplication of a and b is 540:
dividing of a and b is 3.750000:

1. Lazy Linking

  • user_pro.c

#include"header.h"
int main()
{
void* funptr;
int (*add)(int a,int b);
int (*sub)(int a,int b);
int (*mul)(int a,int b);
float (*div)(int a,int b);
funptr = dlopen("/home/student/Narendra/dyna/mylib_shr.so", RTLD_LAZY);
if (!funptr)
{
fprintf(stderr, "Error during dlopen(): %s\n", dlerror());
return 1 ;
}
add= dlsym(funptr, "add");
sub= dlsym(funptr, "sub");
mul= dlsym(funptr, "mul");
div= dlsym(funptr, "div");
int a,b;
printf("Enter a: ");
scanf("%d",&a);
printf("Enter b: ");
scanf("%d",&b);
printf("addition of a and b is %d: ",add(a,b));
printf("\nsubtraction of a and b is %d: ",sub(a,b));
printf("\nmultiplication of a and b is %d: ",mul(a,b));
printf("\ndividing of a and b is %f: ",div(a,b));
printf("\n");
dlclose(funptr);
return 0;
}
  • path
$ pwd
/home/student/Narendra/dyna
  • step 1 : create object code of all .c files
$ cc -Wall -fPIC -c fun1.c fun2.c user_pro.c
$ ls *.o
fun1.o fun2.o user_pro.o
  • step 2 : create shared library with fun1.o and fun2.o
$ cc -shared fun1.o fun2.o
$ mv a.out mylib_shr.so
  • step 3 : create executable file
$ cc -shared fun1.o fun2.o
$ mv a.out mylib_shr.so
  • step 4 : run the executable file
$ ./user_pro_final
Enter a: 45
Enter b: 12
addition of a and b is 57:
subtraction of a and b is 33:
multiplication of a and b is 540:
dividing of a and b is 3.750000:

Windows Environment : DLL files

In windows we use VC++ to create the dll. The following process have to be followed to make the dll.

Creating a Win32 dll

  • Open the New Project Wizard.
  • Select Win32 Dynamic-Link Library.
  • Name the project as dllfun1.
  • In the next screen, select "A dll that exports some symbols" radio button.
  • Click Finish. The dll project will be created.
  • Now open the file dllfun1.cpp. We can see a function definition for "DLLASSIGN_API int fndllfunl(void)".
  • Replace this function with the code of your library function. Like this you can define any number of functions in that file.

  • dllfun1.cpp

// dllfun1.cpp : Defines the entry point for the DLL application.
#include "stdafx.h"
#include "dllfun1.h"
BOOL APIENTRY DllMain( HANDLE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
DLLFUN1_API int add (int a , int b){return a+b;}
DLLFUN1_API int sub (int a , int b){return a-b;}
// This is the constructor of a class that has been exported.
// see dllfun1.h for the class definition
CDllfun1::CDllfun1()
{

return;
}
  • Open the dllfun1.h file and insert the declaration : dllfun1.h
#ifdef DLLFUN1_EXPORTS
#define DLLFUN1_API __declspec(dllexport)
#else
#define DLLFUN1_API __declspec(dllimport)
#endif
// This class is exported from the dllfun1.dll
class DLLFUN1_API CDllfun1 {
public:
CDllfun1(void);
// TODO: add your methods here.
};
DLLFUN1_API int add (int a,int b);
DLLFUN1_API int sub (int a,int b);
  • Create a new file named "dllfun1.Def" and add the following code in that file. : dllfun1.Def
; dllfun1.def : Declares the module parameters for the DLL. LIBRARY "dllfun1"
DESCRIPTION 'DemoDll Windows Dynamic Link Library'
EXPORTS
; Explicit exports can go here
add PRIVATE
sub PRIVATE

  • Add this dllfun1.def into the project.
  • Build the project.The dll will be created.
  • Follow the above steps to create another dll file “dllfun2.dll” that contain function mul and div1.
  • Store both dll files into C:\mydll folder

Using the dll

This part explains only the dynamic loading using loadlibrary. The following sample code I have used in a new console application which uses the library functions defined in dllfun1.dll and dllfun2.dll library.

  • user_pro.cpp

typedef int (*FunPtrTypeInt)(int a,int b);
FunPtrTypeInt add , sub , mul ;
typedef float (*FunPtrTypeFloat)(int a,int b);
FunPtrTypeFloat div1 ;
void main()
{
HINSTANCE hDll;
hDll = LoadLibrary("C:/mydll/dllfun1.dll");
if(hDll == NULL)
{ cout<<"Error loading dllfun1.dll" <<endl;return;
}
add = (FunPtrTypeInt)GetProcAddress(hDll,"add");
if(add == NULL)
{
cout<<"error:"<<GetLastError() <<endl;<<br> }
sub = (FunPtrTypeInt)GetProcAddress(hDll,"sub");
if(sub == NULL)
{
cout<<"error:"<<GetLastError() <<endl;
}
hDll = LoadLibrary("C:/mydll/dllfun2.dll");
if(hDll == NULL)
{
cout<<"Error loading dllfun2.dll"<<endl;
return ;
}
mul = (FunPtrTypeInt)GetProcAddress(hDll,"mul");
if(mul == NULL)
{
cout<<"error:"<<GetLastError() <<endl;<<br> }
div1 = (FunPtrTypeFloat)GetProcAddress(hDll,"div1");
if(div1 == NULL)
{
cout<<"error:"<<GetLastError() <<endl;
}
int a,b;
cout<<"Enter a:";cin>>a;
cout<<"Enter b:";cin>>b;
cout<<"a + b = "<<add(a,b)<<endl;
cout<<"a - b = "<<sub(a,b)<<endl;
cout<<"a * b = "<<mul(a,b)<<endl;
cout<<"a / b = "<<div1(a,b)<<endl;
}
  • running to this program will show the result
Enter a:
45
Enter b:
12
a + b = 53
a - b = 33
a * b = 540
a / b = 3.750000