user1914692
user1914692

Reputation: 3073

In different situations during creating shared libraries, what functions can be called with the lib?

I have read related tutorials regarding shared and static libraries, such as:

"Creating a shared and static library with the gnu compiler [gcc]"

"Static, Shared Dynamic and Loadable Linux Libraries"

However, unfortunately, all examples they used are one function one .c file.

I have two questions:

(1) If I have one file with two more functions, such as example1.c

void ctest11(int *i)
{ *i = 5; }

void ctest12(int *i)
{ *i = 5; }

After compiling exmaple1.c to libexample1.so, can I call ctest11 and ctest12 in it?

(2) If I have one file with two more functions, one of them is a main function, such as example2.c

void ctest21(int *i)
{ *i = 5; }

void main(int *i)
{ *i = 5; }

After compiling exmaple2.c to libexample2.so, is it the same as to compile one .c file with only ctest21 function?

(3) If I have one file example3.c and exmaple4.c The funcion in example3.c will use the function in example4.c For example: example3.c

void ctest31(int *i)
{ *i = ctest41(2,3); }

example4.c

int ctest41(int a, int b)
{ return a+b; }

When I compile example2.c and example3.c to libexample23.so, can I call both ctest31 and ctest41?

But if gcc example2.c example3.o to libexample2.so, I guess I can only call ctest31?

Upvotes: 0

Views: 225

Answers (2)

You should look inside (and build) some existing free software library, compile it, and study its code and building process.

In general, a shared object can be made from several C source files src1sh.c and src2sh.c .... Very often, the compilation is driven by a builder program, usually GNU make

First, you need to compile every source file of the shared object as position-independent-code (PIC) e.g.

gcc -Wall -fPIC src1sh.c -c -o src1sh.pic.o
gcc -Wall -fPIC src2sh.c -c -o src2sh.pic.o

You probably want to add -g to the gcc flags for debugging purposes. Once your program and shared objects are bug free because you have debugged them with gdb and valgrind, pass -O2 to gcc to have them optimized.

Then you need to link all these PIC object files into a single shared object (a *.so file), like

gcc -shared src1sh.pic.o src2sh.pic.o -o shared.so

If your intent is to make a shared library call it lib*.so e.g. libfoo.so and refer to it as -lfoo flag to the linking gcc command using your shared library.

Notice that linking a shared object may also link other shared libraries, so you could do

gcc -shared src1sh.pic.o src2sh.pic.o -lsome -o shared.so

to link some libsome.so into your shared.so

You usually don't compile a shared object containing a main (remember that main is a very special function, described specifically in the C standard, and called from the startup code crt*.o linked by gcc into every program); this is nearly non-sense (like your libexample2.so). Your main is defined in your program (and you don't need PIC code for your program executable). If your program is made from source files src1pr.c and src2pr.c (which defines main) you first compile them as

gcc -Wall src1pr.c -c -o src1pr.o
gcc -Wall src2pr.c -c -o src2pr.o

and you link them all with e.g.

gcc src1pr.o src2pr.o -o prog -lshared

where -lshared refers to a shared library libshared.so (you probably want to compile and link your program files with -g for debugging information, and you may want to pass additional -I flags for include directories, and -L flags for library directories, e.g. -L. to search library in the current directory ...)

There is a way to dynamically link at runtime some shared object, notably for having plugins. You then want to use the dlopen & dlsym functons for that (and you usually want to link your main program with -rdynamic flag).

You can call (from your program) any visible function inside a shared object. You may want to play with the visibility function attribute to e.g. restrict the visibility of some function inside your shared object. You might perhaps want to later use the constructor attribute, for a function inside a shared object to be called early at initialization time (if it is a plugin, at its dlopen time).

Read Program Library Howto and Levine's "Linkers and Loaders" book for more. Linux shared objects (and relocatable object *.o, and executable binaries) are in Executable & Linkable Format (ELF is an industry standard). Some further details are described in the Application Binary Interface (and notably the ABI supplement for your processor, e.g. AMD64 ABI supplement).

PS. You really want a builder like GNU make to combine all these steps, so read its documentation. You might want to pass -v to gcc to understand what it is doing...

Upvotes: 1

user1914692
user1914692

Reputation: 3073

Thanks for Basile' great explanation. From what I understand, related to my questions,

(a) For my first question (1), there are multiple functions in one object file. I can call ctest11 and ctest12 in libexample1.so

I may set visibility to the functions in libexample1.so.

(b) For my third question (3), the firs scenario is related to create a library from two object files. I can call any functions in the files. The second scenario is related to create a library and link with another library. I can call any functions in the libraries, including the linking library.

(3) I still do not understand the situations with a main function. You said, "You usually don't compile a shared object containing a main; this is nearly non-sense (like your libexample2.so). "

I knew it is non-sense. But if I do not want to change the program file, and want to compile it to a library, say, in example2.c, I compile it to example2.so, and want to call the function ctest21. Can I do that?

example2.c

void ctest21(int *i)
{ *i = 5; }

void main(int *i)
{ *i = 5; }

I compile it to a library.

gcc -fPIC -g -c -Wall example2.c
gcc -shared -o libexample2.so example2.o 

I think I can call crest21 function in example2.o. But the main function is useless. Is my understanding correct?

Upvotes: 0

Related Questions