How to run c program with .so file - c

I have gone through all the solutions on StackOverflow as well as Ask Ubuntu.
I have a Go program:
package main
import "C"
//export Getint
func Getint() int {
return 2
}
func main() {}
and I have generated .so file for the same with name t.so and header filet.h`
Now I would like to use this function in my C program.
I have written the code but I don't know how to execute it.
#include <stdio.h>
#include <t.h>
int main()
{
int a;
a=Getint();
printf("number : %d",a);
return 0;
}
When I execute it with
gcc c.c t.so
it generates a.out file
but at the time of running a.out with ./a.out it gives an error:
./a.out
Error while loading shared libraries: t.so: can not open shared object file: no such file or directory exists.
then I tried with:
gcc -c c.c -l t.so
So it generates c.o file and it is not executable.

You should use the linker option -rpath, which tells the linker to add information in the executable program where to find runtime libraries like your .so file.
This can be done using the GCC option -Wl which instructs the GCC frontend program to pass an option to the linker:
$ gcc c.c t.so -Wl,-rpath=$(pwd)
This will pass -rpath=$(pwd) to the linker, and $(pwd) causes the shell to call the pwd command to return the current directory.
As long as you don't move the library the program should work.
You can use the environment variable LD_LIBRARY_PATH too, but it's not recommended.

Most probably your loader cannot find the library. Try to put the path to the directory where the libarry is located to LD_LIBRARY_PATH prior to run your binary.
export LD_LIBRARY_PATH=/path/to/my/library
./a.out

.so files are shared object, meaning object that are available to all applications that need them.. that is, shared. Due to this characteristics, they need to be stored in a well known place. Also, they need to be indexed by the dynamic linker.
In linux for instance you typically have a file /etc/ld.so.conf where all directories where shared object are automatically read from are stored
So your options are:
Put your shared object file in a well known place
Put your shared object file in a place of your choice and let the dynamic linker know about it: in linux you can modify ld.so.conf and run ldconfig to update ld indexes
As other suggested write the path of your .so in the env variable LD_LIBRARY_PATH (since dynamic linker reads it before running your application). This must be done at each environment creation
As other suggested use -rpath when compiling. Note that in this way you cannot move your .so file after the compilation
Personally I prefer installing the .so file in a system library path

You should use LD_LIBRARY_PATH to let the dynamic linker find your shared library in the list. Syntax is similar to PATH a list of directories separted by :.
On OSX this environment variable is called DYLD_LIBRARY_PATH.

Related

Compiling dynamically linked library in a makefile

I am trying to run my library using a make file. I currently have a dynamic library called libname.so which I created by linking the object files of some of my C files. This library works correctly when I run the following lines of code in my linux shell :
gcc -L. main1.c -lname -o out
LD_LIBRARY_PATH=.
export LD_LIBRARY_PATH
But when I copy these exact lines of code in to a make file and name the make file title for this function 'names' and then run 'make names' in linux shell, I get the following error:
./out: error while loading shared libraries: libname.so: cannot open shared object file: No such file or directory
Then once again when I run the final two lines of code shown at the end of the makefile function again then run the out file, it is fixed and the program works again.
I just need to figure out how to make it work directly from the makefile.
LD_LIBRARY_PATH=.
export LD_LIBRARY_PATH
These two lines do not influence the creation of the program in any way because you type the lines after creating the program.
These lines are not used for building your program, but they influence running the program (by typing ./out).
If you compile your program using gcc directly (not using make) and open a new terminal, you also have to type these two lines (again) before you run the program.
It does not matter how you build the program (by typing gcc manually or by running make):
After opening a new terminal, you will need to type these two lines before you run the program.
However, the dynamic linker does not only use the path information from LD_LIBRARY_PATH but also from the DT_RUNPATH information in the executable.
Unlike the LD_LIBRARY_PATH variable which is set on one console (or terminal) only, the DT_RUNPATH information is stored directly in the executable file.
As described in another question on this site, you can set the DT_RUNPATH information using the -Wl,-rpath=<value> switch:
gcc -L. main1.c -lname -o out -Wl,-rpath=.
If you do this, the dynamic linker will search your library (libname.so, if I understand correctly) in the current directory.
Note:
. really means: In the current directory; it does not mean: In the same directory as the executable file!
If your program is stored in the directory ./somedir and you type somedir/out, the file ./libname.so is searched, not the file ./somedir/libname.so.
This is both the case for the -Wl,-rpath= method and for the LD_LIBRARY_PATH= mehtod.

How to debug "cannot open shared object file: No such file or directory"?

On our project at work, where I use a build system managed by another team, I am running into an issue where I am able to compile and link the binary, but then when executing it, it complains about being unable to load a shared object file, it should never have been linked against:
/home/me/build/bin/executable: error while loading shared libraries: libicui18n.so.52.1: cannot open shared object file: No such file or directory
The curious part is, that the only instance of the file name libicui18n.so.52.1 I can even find on my machine are /opt/onlyoffice/desktopeditors/libicui18n.so.52.1 and /home/me/.local/opt/foxitsoftware/foxitreader/lib/libicui18n.so.52.1, which I definitely don't link against, at least according to linker command executed by the build system:
It does not occur as any of the explicit /absolute/path/to/libsomething.so.42.3 files.
Nothing related is given as -L option.
Nothing related is given as /absolute/path/to/libsomething.a file.
Nothing related is in $LD_LIBRARY_PATH or $LIBRARY_PATH.
The Intel Fortran compiler has no reason to include those in the default paths.
So now I am wondering, how else the libicui18n.so.52.1 may be linked against, and how I may go about debugging such an issue.
how else the libicui18n.so.52.1 may be linked against
ELF libraries can specify "what name should be used at runtime" independently of the name of the library itself. Example:
gcc -fPIC -shared -o libt.so t.c -Wl,--soname=libfoo.so.1.2.3
gcc main.c -L. -lt
./a.out
./a.out: error while loading shared libraries: libfoo.so.1.2.3: cannot open shared object file: No such file or directory
Here, the library is built in a way which requires libfoo.so.1.2.3 at runtime, although no such library exists. It is up to the packaging system to provide such library (or a symlink).
You can examine a library to see what name it expects to be used at runtime like so:
readelf -d libt.so | grep SONAME
0x000000000000000e (SONAME) Library soname: [libfoo.so.1.2.3]
You can examine the list of libraries a.out requires at runtime like so:
readelf -d ./a.out | grep NEEDED
0x0000000000000001 (NEEDED) Shared library: [libfoo.so.1.2.3]
0x0000000000000001 (NEEDED) Shared library: [libc.so.6]
how I may go about debugging such an issue.
As above. Your next question is probably "how can I fix this issue?".
Since libicui18n.so.52.1 is installed, but not installed into a directory which the dynamic linker will search by default, all you have to do is tell your binary to add the non-standard /opt/onlyoffice/desktopeditors directory the list of directories to search.
You do that by adding -Wl,-rpath=/opt/onlyoffice/desktopeditors to your executable's link line.
You can also add /opt/onlyoffice/desktopeditors to LD_LIBRARY_PATH, but using -Wl,-rpath is preferred.

Can't link dynamic library when running C language with root privileges?

I have a C language file named testFunc.c that uses the dynamic library libCfunc.so. This library is placed under the path /home/cuiyujie/workspace/library/lib.
I added this path to library path export LD_LIBRARY_PATH=/home/cuiyujie/workspace/library/lib:$LD_LIBRARY_PATH
When I use the following command to compile, it can be compiled normally.
gcc testFunc.c -lCfunc -lm -O0 -g -o testFunc
But when I run it, if I use ./testFunc, it can run normally.
But if I use sudo ./testFunc, he will get the following error.
./testFunc: error while loading shared libraries: libCfunc.so: cannot
open shared object file: No such file or directory
I found on Google that when root is used, the value of the LD_LIBRARY_PATH variable is ignored.
I used the following command to recompile. Specify the library path when compiling.
gcc testFunc.c -L/home/cuiyujie/workspace/library/lib -lCfunc -lm -O0 -g -o testFunc
When I continue to run with the sudo ./testFunc command, the same error still appears.
The reason why I need to execute with root is because I need to read some inquiries that only root privileges can read. I want to get the physical address of certain variables, so I need to read the mapping file of the process, which requires root privileges.
The linker flag -L just tells the linker where to look for the library (or a library stub, if such is used) at link time. It does not influence the library search path at runtime.
For a system wide installed library you'd place the library in a place that's been configured in the global linker search path, set through /etc/ld.so.conf and files in /etc/ld.so.conf.d.
However it is perfectly possible to specify additional search paths specific to certain binaries by means of the so callled rpath. The rpath is set using the (you guessed it) rpath extra linker flag -Wl,-rpath.
Linking the program with
gcc -o … -Wl,-rpath='${ORIGIN}' …
would make the ELF interpreter (the piece of code that loads ELF binaries and does dynamic linkage) to also look for additional libraries right next to the program binary. You can read up on the details of rpaths in the ld.so manpage.
Be aware that rpaths invoke certain security considerations.
LD_LIBRARY_PATH is an environment variable, and all environment variables exist separately for each user.
When you export it under your regular user, but then run the executable as root using sudo, the export does not exist for the new process.
You can preserve the environment of your user with the -E parameter:
sudo -E ./testFunc
or you can specifically preserve the LD_LIBRARY_PATH variable like this:
sudo LD_LIBRARY_PATH=/home/cuiyujie/workspace/library/lib:$LD_LIBRARY_PATH ./testFunc

How to use functions in a package that is written in C in a different location

I am trying to use a linear algebra package called hnfprof. I have done the installation with the given instructions and now its ready to use. Now I want to use some functions in hnfproj/src/lift/lift.c file. I want to create my own matrix examples and check outputs for each functions separately. I am not clear how to do this. (I know only basics of C language, creating .c files in a folder and running it in my Ubuntu terminal.)
I know that I should write a C file including this "#include <lift.c>" file name and creating a matrix in my file "main.c". I don't know how to include a file name in a different location. When I compile I can not use "gcc -o program main.c lift.c". My "main.c" file is in a different folder. I don't want to create any make file inside the package folder. So how I can just use the "lift.c" file inside my "main.c" file which is in a separate folder "Main" and create all executable make files inside "Main" folder?
If its difficult to give a answer, appreciate if you can suggest me some source to learn this. Thank you
No need to include lift.c directly in main.c, and you can call function in lift.c from main.
When it comes to compilation, you can use:
gcc -o program main.c file_location/lift.c
If you need other options, add them (most flags at the start; libraries at the end, after the source code). You can also compile each file to object code separately and then link the object files together:
gcc -c main.c
gcc -c file_location/lift.c
gcc -o program main.o lift.o
refer
Compiling multiple C files with gcc

How to write common functions for reusing in C

I was trying to write a common function for other files could reuse it, the example as following, I have three files:
The first file: cat test1.h
void say();
The second file: cat test1.c
void say(){
printf("This is c example!");
}
The third file: cat test2.c
include "test1.h"
void main(){
say();
}
but when I ran: gcc -g -o test2 test2.c
it threw error as:
undefined reference to `say'
Additionally: I knew this would work:gcc -g -o test2 test1.c test2.c
but I don't wanna do this, because the other team would use the server, and I hope them directly use my binary code not source code. I hope that just like we use printf() function, we just need include .
You can build yourself a library from the object files containing your useful functions, and store the header(s) that describe them in a convenient location. You and your colleagues then compile with the headers and link that library with any executables that use any of those functions. That's very much the same general mechanism that the C compiler uses to include the standard headers and automatically link with the standard C library.
The mechanics vary a bit depending on platform (Windows vs Unix being the primary distinction, though there are differences between Unix platforms too), and also on the type of library (static archive vs dynamic linked / loaded libraries — also known as shared objects or shared libraries).
In broad outline, for a Unix system with a static library, you'd:
Compile library object files libfile1.o, libfile2.o, … using (for example) gcc -c libfile1.c libfile2.c.
Create an archive from the object files — using for example ar r libname.a libfile1.o libfile2.o.
Copy the headers to a standard location such as /usr/local/include.
Copy the library to a standard location such as /usr/local/lib.
You'd compile any code that uses the library functions with -I/usr/local/include (if that is not already a standard compilation option).
You'd link the programs with -L/usr/local/lib -lname (you might not need to specify -L… but you would need to specify -lname).
Including a header file does not make a function available. It simply informs the compiler that the function will be provided at a later time.
You should compile the file with the function into a shareable object file (or a library if there is more than one function that you want to share). Mind the switch -c which tells gcc not to build an executable file:
gcc -o test1.o test1.c -c
Similarly, compile the main function into its own object file. Now you or anyone else can link the object file with their main program:
gcc -o test2 test2.o test1.o
The process can be automated using make.
Other programmers can use compiled object files (`*.o') in their programs. They need only to have a header file with function prototypes, extern data declarations and type definitions.
You can also wrap many object files into the library.
On many systems you can also create the dynamic linked libraries which do not have to be linked into the executable.
you also need to compile test1:
gcc -g -o test2 test1.c test2.c.

Resources