When you write an software utilizing the C programming language, your code normally has a number of supply information.
Ultimately, these information have to be compiled right into a single executable. You can do that by creating both static or dynamic libraries (the latter are additionally known as shared libraries). These two kinds of libraries differ in how they’re created and linked. Both have benefits and drawbacks, relying in your use case.
Dynamic linking is the most typical methodology, particularly on Linux techniques. Dynamic linking retains libraries modular, so only one library may be shared between any variety of purposes. Modularity additionally permits a shared library to be up to date independently of the purposes that depend upon it.
In this text, I reveal how dynamic linking works. In a future article, I’ll reveal static linking.
Linker
A linker is a command that mixes a number of items of a program collectively and reorganizes the reminiscence allocation for them.
The features of a linker embrace:
- Integrating all of the items of a program
- Figuring out a brand new reminiscence group so that every one the items match collectively
- Reviving addresses in order that this system can run below the brand new reminiscence group
- Resolving symbolic references
As a results of all these linker functionalities, a runnable program referred to as an executable is created. Before you may create a dynamically linked executable, you want some libraries to hyperlink to and an software to compile. Get your favorite text editor prepared and comply with alongside.
Create the thing information
First, create the header file mymath.h
with these operate signatures:
int add(int a, int b);
int sub(int a, int b);
int mult(int a, int b);
int divi(int a, int b);
Create add.c
, sub.c
, mult.c
and divi.c
with these operate definitions. I’m inserting all the code in a single code block, so divide it up amongst 4 information, as indicated within the feedback:
// add.c
int add(int a, int b){
return (a+b);
}//sub.c
int sub(int a, int b){
return (a-b);
}//mult.c
int mult(int a, int b){
return (a*b);
}//divi.c
int divi(int a, int b){
return (a/b);
}
Now generate object information add.o
, sub.o
, mult.o
, and divi.o
utilizing GCC:
$ gcc -c add.c sub.c mult.c divi.c
The -c
choice skips the linking step and creates solely object information.
Creating a shared object file
Dynamic libraries are linked through the execution of the ultimate executable. Only the identify of the dynamic library is positioned within the remaining executable. The precise linking occurs throughout runtime, when each executable and library are positioned in the principle reminiscence.
In addition to being sharable, one other benefit of a dynamic library is that it reduces the dimensions of the ultimate executable file. Instead of getting a redundant copy of the library, an software utilizing a library contains solely the identify of the library when the ultimate executable is created.
You can create dynamic libraries out of your present pattern code:
$ gcc -Wall -fPIC -c add.c sub.c mult.c divi.c
The choice -fPIC
tells GCC to generate position-independent code (PIC). The -Wall
choice is not needed and has nothing to do with how the code is compiling. Still, it is a beneficial choice as a result of it permits compiler warnings, which may be useful when troubleshooting.
Using GCC, create the shared library libmymath.so
:
$ gcc -shared -o libmymath.so
add.o sub.o mult.o divi.o
You have now created a easy instance math library, libmymath.so
, which you need to use in C code. There are, in fact, very advanced C libraries on the market, and that is the method their builders use to generate the ultimate product that you just or I set up to be used in C code.
Next, you need to use your new math library in some customized code, then hyperlink it.
Creating a dynamically linked executable
Suppose you have written a command for arithmetic. Create a file referred to as mathDemo.c
and paste this code into it:
#embrace <mymath.h>
#embrace <stdio.h>
#embrace <stdlib.h>int primary()
{
int x, y;
printf("Enter two numbersn");
scanf("%d%d",&x,&y);
printf("n%d + %d = %d", x, y, add(x, y));
printf("n%d - %d = %d", x, y, sub(x, y));
printf("n%d * %d = %d", x, y, mult(x, y));if(y==0){
printf("nDenominator is zero so can't perform divisionn");
exit(0);
}else{
printf("n%d / %d = %dn", x, y, divi(x, y));
return 0;
}
}
Notice that the primary line is an embrace
assertion referencing, by identify, your individual libmymath
library. To use a shared library, you could have it put in. If you do not set up the library you utilize, then when your executable runs and searches for the included library, it will not have the ability to discover it. Should you have to compile code with out putting in a library to a recognized listing, there are ways to override default settings. For common use, nevertheless, it is anticipated that libraries exist in recognized places, so that is what I’m demonstrating right here.
Copy the file libmymath.so
to a regular system listing, corresponding to /usr/lib64
, after which run ldconfig
. The ldconfig
command creates the required hyperlinks and cache to the newest shared libraries present in the usual library directories.
$ sudo cp libmymath.so /usr/lib64/
$ sudo ldconfig
Compiling the appliance
Create an object file referred to as mathDemo.o
out of your software supply code (mathDemo.c
):
$ gcc -I . -c mathDemo.c
The -I
choice tells GCC to seek for header information (mymath.h
on this case) within the listing listed after it. In this case, you are specifying the present listing, represented by a single dot (.
). Create an executable, referring to your shared math library by identify utilizing the -l
choice:
$ gcc -o mathDynamic mathDemo.o -lmymath
GCC finds libmymath.so
as a result of it exists in a default system library listing. Use ldd
to confirm the shared libraries used:
$ ldd mathDemo
linux-vdso.so.1 (0x00007fffe6a30000)
libmymath.so => /usr/lib64/libmymath.so (0x00007fe4d4d33000)
libc.so.6 => /lib64/libc.so.6 (0x00007fe4d4b29000)
/lib64/ld-linux-x86-64.so.2 (0x00007fe4d4d4e000)
Take a have a look at the dimensions of the mathDemo
executable:
$ du ./mathDynamic
24 ./mathDynamic
It’s a small software, in fact, and the quantity of disk house it occupies displays that. For comparability, a statically linked model of the identical code (as you will see in my subsequent article) is 932K!
$ ./mathDynamic
Enter two numbers
25
525 + 5 = 30
25 - 5 = 20
25 * 5 = 125
25 / 5 = 5
You can confirm that it is dynamically linked with the file
command:
$ file ./mathDynamic
./mathDynamic: ELF 64-bit LSB executable, x86-64,
dynamically linked,
interpreter /lib64/ld-linux-x86-64.so.2,
with debug_info, not stripped
Success!
Dynamically linking
A shared library results in a light-weight executable, because the linking occurs throughout runtime. Because it resolves references throughout runtime, it does take extra time for execution. However, for the reason that overwhelming majority of instructions on on a regular basis Linux techniques are dynamically linked and on trendy {hardware}, the time saved is negligible. Its inherent modularity is a robust function for builders and customers alike.
In this text, I described tips on how to create dynamic libraries and hyperlink them right into a remaining executable. I’ll use the identical supply code to create a statically linked executable in my subsequent article.