The code for the library:
calc_mean.c
//#include <stdio.h>
double mean(double a, double b) {
return (a+b) / 2;
}
The header file:
calc_mean.h
double mean(double, double);
The programm using the library:
main.c
#include <stdio.h>
#include "calc_mean.h"
int main(int argc, char* argv[]) {
double v1, v2, m;
v1 = 5.2;
v2 = 7.9;
m = mean(v1, v2);
printf("The mean of %3.2f and %3.2f is %3.2f\n", v1, v2, m);
return 0;
}
I created static library using following commands:
gcc -c calc_mean.c -o calc_mean.o
ar rcs libmean.a calc_mean.o
Linking against static library:
gcc -static main.c -L. -lmean -o statically_linked
everything works perfectly fine as long as its static library...
Now these are the commands which I used to create shared library:
gcc -c -fPIC calc_mean.c -o calc_mean.o
gcc -shared -Wl,-soname,libmean.so.1 -o libmean.so.1.0.1 calc_mean.o
after these two commands when I enter the linkng command
gcc main.c -o dynamically_linked -L. -lmean
I am getting error message can not find -lmean
ld returned 1 exit status
attaching error message here
can some one give me steps to create DLL in C?
This is because you are creating a file named libmean.so.1.0.1, but you ask the linker to link with libmean.so (this is what -lmean expands to).
You need a symbolic link libmean.so pointing to libmean.so.1.0.1.
When you try to link the lib by giving -lmean, it automatically searches for libmean.so, but you have created the lib as libmean.so.1.0.1. This is the problem. Either change the lib name or create a symbolic link.
Did you copy the libmean.so.1 in /usr/lib/ (or) /opt/lib/?
Related
I am forced to link two version of the same third party dynamic library (Linux .so, C language) into the same executable to support old and new functionality in the same process. Having two executables or remote services are undesirable.
I made the assumption that this must be a doable task. I tried to experiment with the naive approach of creating 2 proxy dynamic libraries each linked against one of the real libraries and have function renamed.
Unfortunately, this attempt failed – both new functions call the same target function.
I still want to believe that the problem is in the lack of my knowledge as there are plenty of compiler and linker ( gcc and ld) options.
I will appreciate any help. I also look forward to using dlopen/dlsym, but first want to check if the original approach can work.
Here is the sample code
/* ./old/b.c */
#include <stdio.h>
int b (int i)
{
printf("module OLD %d\n",i);
return 0;
}
/* ./old/Makefile */
libold.so: b.c
gcc -c -g b.c
gcc -shared b.o -o $#
/* ./new/b.c */
#include <stdio.h>
int b (int i)
{
printf("module new %d\n",i);
return 0;
}
/* ./new/Makefile */
libnew.so: b.c
gcc -c -g b.c
gcc -shared b.o -o $#
/* ./a1.c */
#include <stdio.h>
int b(int);
void call_new(void)
{
printf("will call new 1\n");
b(1);
printf("called new 1\n");
}
/* ./a2.c */
#include <stdio.h>
int b(int);
void call_old(void)
{
printf("will call old 2\n");
b(2);
printf("called old 2\n");
}
/* ./main.c */
#include <stdio.h>
int call_new(void);
int call_old(void);
int main()
{
call_new();
call_old();
return 0;
}
/* ./Makefile */
.PHONY: DEPSNEW DEPSOLD clean
main: liba1.so liba2.so main.c
gcc -c main.c
gcc -o main main.o -rdynamic -Wl,-rpath=new -Wl,-rpath=old -L . -la1 -la2
DEPSNEW:
make -C new
DEPSOLD:
make -C old
liba1.so: DEPSNEW a1.c
gcc -c -fpic a1.c
gcc -shared a1.o -L new -lnew -o liba1.so
liba2.so: DEPSOLD a2.c
gcc -c -fpic a2.c
gcc -shared a2.o -L old -lold -o liba2.so
clean:
find -name "*.so" -o -name "*.o" -o -name main | xargs -r rm
/* ./run.sh */
#/bin/sh
LD_LIBRARY_PATH=new:old:. main
The result is not that I want - function from "new" library is called twice
will call new 1
module new 1
called new 1
will call old 2
module new 2
called old 2
In this case, you can not control the automatic loading of the dynamic library in order to assure which library will be loaded for the depending libraries. What you can do, is to use one of the libraries (the new one) for the dynamic linker and to link the second library manually as follows:
Add function to dynamically load and link the function from the library.
a2.c
#include <stdio.h>
#include <dlfcn.h>
static int (*old_b)(int);
void init_old(void) {
void* lib=dlopen("./old/libold.so", RTLD_LOCAL | RTLD_LAZY);
old_b=dlsym(lib,"b");
}
void call_old(void)
{
printf("will call old 2\n");
old_b(2);
printf("called old 2\n");
}
call the initialization function
main.c
#include <stdio.h>
void init_old(void);
int call_new(void);
int call_old(void);
int main()
{
init_old();
call_new();
call_old();
return 0;
}
Modify the linker options to add the dynamic loading library -ldl
liba2.so: DEPSOLD a2.c
gcc -c -fpic a2.c
gcc -shared a2.o -L old -lold -ldl -o liba2.so
After this modification
~$ ./run.sh
will call new 1
module new 1
called new 1
will call old 2
module OLD 2
called old 2
I have a program which is linked (dynamically) with libm.
There are also several plugins for this program.
Plugins are loaded explicitely with dlopen().
Some of these plugins use round() from libm.
On one system (Linux Mint 19.1 gcc 7.5.0) the program
does not work because of unresolved round.
Here is simple example:
Library (lib.c)
#include <stdio.h>
#include <math.h>
void func(double a, double b)
{
double c;
c = round(a + b);
printf("c = %lf\n", c);
}
Main program (main.c)
#include <stdio.h>
#include <dlfcn.h>
void *dll;
void (*f)(double, double);
double a = 1.234, b = 4.321;
int main(void)
{
dll = dlopen("./lib.so", RTLD_LAZY);
f = dlsym(dll, "func");
f(a,b);
return 0;
}
Building (Makefile)
all:
gcc -Wall -Os -shared -fPIC lib.c -o lib.so
gcc -Wall -Os -rdynamic -fPIC main.c -o main -ldl -lm
Run on Debian 8, gcc 4.9.2
./main
c = 6.000000
Run on Linux Mint 19.1, gcc 7.5.0
./main
./main: symbol lookup error: ./lib.so: undefined symbol: round
Now, add -lm for dll compilation
gcc -Wall -Os -shared -fPIC lib.c -o lib.so -lm
./main
c = 6.000000
So, the question is - why on this particular system one must use -lm not only for main program but for plugin also?
Just like an executable program, shared libraries are linked entities (unlike static libraries which are archives of object files).
Since shared libraries are linked like executables, you also need to link with the libraries that your library depends on:
gcc -Wall -Os -shared -fPIC lib.c -o lib.so -lm
Hello beautiful people,
i'm trying to create a static libary and to compile against it.
I've allready created a small static libary and a header for it.
Header (math.h):
int add (int a, int b);
int sub (int a, int b);
add.c:
int add (int a, int b) { return a + b; }
sub.c:
int sub (int a, int b) { return a - b; }
I've created my static libary with the following commands:
gcc -c add.c
gcc -c sub.c
ar rcs libmymath.a add.o sub.o
Now my main.c
#include <stdio.h>
#include "math.h"
int main( int argc, char **argv ) {
printf("Result : %d\n", add(5,7) );
return 0;
}
I can compile it with the following command:
gcc main.c libmymath.a -o main
But if i compile it the following way, it fails.
gcc main.c -lmymath -L. -o main
It fails with the following error:
/usr/bin/ld: cannot find -lmymath collect2:
error: ld returned 1 exit status
even a change to
gcc main.c -llibmymath -L. -o main
fails and even if i include the header mymath.h to gcc
Can you help me ?
gcc understood -lmymath by libmath.so or libmath.a already. So when you add lib word in -llibmymath. This case the gcc understood your library name being liblibmymath.a. So, please replace this command
gcc main.c -llibmymath -L. -o main
by
gcc main.c -o main -L. -lmymath
It should work.
I was looking here how to do static libraries using GCC, and the explanation is pretty clear (despise the fact I had to rewrite the factorial function): I have a function (fact.c), the header of the function (fact.h), and the main function (main.c), all of them in my home directory.
fact.h
int fact (int);
fact.c
int
fact (int f) {
if ( f == 0 )
return 1;
else
return (f * fact ( f - 1 ));
}
main.c
#include <stdio.h>
#include "fact.h"
int main(int argc, char *argv[])
{
printf("%d\n", fact(3));
return 0;
}
So I had first to generate the object file (phase 1)...
$ gcc -c fact.c -o fact.o
...then to generate the static library (phase 2)...
$ ar rcs libfact.a fact.o
...later to do the static library linking process (phase 3)...
$ gcc -static main.c -L. -lfact -o fact
...and finally run the program (phase 4 and final)
$ ./fact
My question is the following. Let's suppose my program will be so big that I had no alternative than put the headers in a header directory (/include/fact.h) and the static libraries will also be in another directory (/lib/libfact.a). In that case, how the compilation and/or the code of this program will change?
Edit/Problem Solved: First, the main.c was corrected in order to include a header in another directory called include. Remember that, in this case, both of the .c files are in the main directory.
main.c
#include <stdio.h>
#include "include/fact.h"
int main(int argc, char *argv[])
{
printf("%d\n", fact(3));
return 0;
}
Second, to generate the static library in another directory (phase 2), this is what I had done:
$ ar rcs lib/libfact.a fact.o
Here is your answer,
$ gcc -static main.c -L. -lfact -o fact
-L Add directory to the list of directories to be searched for -l
Its in the link that you gave. If you put the seach direction correctly and low search range, it will not be a problem. Otherwise it is not going to compile the code. Because code did not know where is the header.
You can add -I to specify include path(s).
gcc -I/include fact.c
gcc -I/include -static main.c -L/lib -lfact -o fact_main
In libname.h:
int add_libname(int, int);
In libname.c:
#include "libname.h"
int add_libname(int a, int b)
{
return a+b;
}
I can build the shared library this way:
gcc -shared -fPIC libname.c -o libname.so
But I can't use it in another programe test.c:
#include <stdio.h>
#include "libname.h"
int main(int argc, char* argv[])
{
printf("%d\n", add_libname(1,5));
}
Reporting undefined reference to add_libname when I try to build it..
What's wrong here?
Because add_libname takes (int, int) you're giving it (1+5 = 6) or just (int)
I think you meant
add_libname(1, 5);
Also to compile it correctly you must use gcc like so
gcc -o myapp test.c -L. -lname
the lib part of libname is ignored as it is implicit
To create a shared library use these
gcc -fPIC -c libname.c
it gives warning: position independent code and libname.o file is generated.
and now type these command,
gcc -shared libname.so libname.o
libname.so ( the shared library is created with .so extension). To use the shared library
gcc -I/give the path of libname.h sourcefile.c /give the path of your .so file
example if your c file is file.c and the header file libname.h is in c:\folder1\project and your libname.so (shared library) is in c:\folder\project2
then
gcc -I/cygdrive/c/folder1/project file.c /cygdrive/c/folder/project/libname.so
this is the gcc command to be used while using the shared library.
Thank you.