Can't load dll in linux gcc - c

I'm trying to compile my code with a DLL i made and I get the error below when i write ./prog
./prog: error while loading shared libraries: libctest.so.1: cannot open shared object file: No such file or directory
I followed the tutorial here and my mono app has no problem loading the dll and calling the functions. The key parts of the tutorial were
gcc -Wall -fPIC -c *.c
gcc -shared -Wl,-soname,libctest.so.1 -o libctest.so.1.0 *.o
mv libctest.so.1.0 /opt/lib
ln -sf /opt/lib/libctest.so.1.0 /opt/lib/libctest.so.1
ln -sf /opt/lib/libctest.so.1.0 /opt/lib/libctest.so
My C# code does
[DllImport("path/to/CDLL", CallingConvention = CallingConvention.Cdecl)]
public static extern void test();
I built with
gcc -Wall -L/opt/lib main.c -lctest -o prog
This is the first thing i changed. prog.c to main.c. From there I simply run with ./prog to get the error at the top of this question. I do this as root so there shouldn't be permission issues. I also chmod 755 the so's. What am I doing wrong? This is opensuse. I had to create the /opt/lib so I am thinking this path isn't registered where it should be

The dynamic linker ld.so will not look in /opt/lib by default when attempting to resolve library dependencies. You have to tell the linker about the non-standard library directories or add the /opt/lib path to your prog binary.
eg
LD_LIBRARY_PATH=/opt/lib ./prog
or, link prog with the -rpath linker option. This provides an additional path for the linker to search when resolving locations of shared objects.
gcc -Wall -L/opt/lib -Wl,-rpath,/opt/lib main.c -lctest -o prog
You can use the ldd command on a binary to show the locations of shared libraries.
ldd prog
This will currently show that libctest.so cannot be found. With an additional search path, the following command should show that all libraries are resolved:
LD_LIBRARY_PATH=/opt/lib ldd prog

Related

Dynamic linker gives "cannot open shared object file: No such file or directory" after using -L option

I have a project struct of a lib like this:
lib_ode/
src/
main/
c/
ode.c
incluce/
ode.h
test/
c/
test_ode.c
include/
target/
.objs/
test/
In this struct I had compile my project with those 4 commands:
(creating lib object)
gcc -fPIC -O3 -DNDEBUG -g -Wall -Isrc/main/include -c -o "target/.objs/ode.o" src/main/c/ode.c
(creating lib)
gcc -shared target/.objs/ode.o -lm -o "target/libode.so"
(creating test object)
gcc -fPIC -O3 -DNDEBUG -g -Wall -Isrc/main/include -c -Isrc/test/include -o target/.objs/test.o src/test/c/test_ode.c
(creating test)
gcc -L./target -lode target/.objs/test.o -o target/test/test.out
Then I tryed to run target/test/test.out and got this error.
target/test/test.out: error while loading shared libraries: libode.so: cannot open shared object file: No such file or directory
In my understand, -L option includes a folder for link, and after the second command I can find a file at target/libode.so.
So what am I doing wrong?
You have created an executable dynamically linked against a library in an arbitrary directory. At runtime, the dynamic linker cannot find the library (it doesn't exist in any of the standard search paths) and so gives you the error.
To run the program, you could set the LD_LIBRARY_PATH environment variable:
LD_LIBRARY_PATH="`pwd`/target" target/test/test.out
You could also trying linking with -rpath (I've not tried this):
gcc -L./target -Wl,-rpath,./target -lode target/.objs/test.o -o target/test/test.out
(The above should "hardcode" the additional dynamic library search path in the executable. If you later move the library you will get an error again. I'm not sure if the path stored in the executable will be relative or absolute; if it's relative, you'll need to keep the executable and library at the same path relative to each other).

Using makefile, LD_PRELOAD to executable file

I have two files, "abc.c" and "run"
and I want to make a executable binary file which perform below two intstructions
gcc -m32 -O2 -Wall -DRUNTIME -shared -fPIC -o a.so abc.c -ldl
LD_PRELOAD="a.so" ./run
I tried to use makefile in linux, but failed.
Can I use makefile to make executable binary file ?
Ideally, makefile should be used for compilation. For automating the shell commands, you can use a shell script.
Maybe, in your case, you can write a shell script, which will call the make -f <SomeMakeFile> command first to compile and generate the library (.so) and then run the target binary with alogwith the LD_PRELOAD instruction.
I'd do it like this:
all: a.so
test: a.so
LD_PRELOAD="a.so" ./run
a.so: abc.c
gcc -m32 -O2 -Wall -DRUNTIME -shared -fPIC -o a.so abc.c -ldl
clean:
rm -f a.so
Save this in a file called Makefile. Note that the indentations MUST be a single tab - stackoverflow ruined that in their output above.
There are now 4 targets, calling just make will generate the shared library, explicitly calling make test will run your test. If needed, make test will build the library first.
I was tempted to throw in some more flexibility, but that was not what you asked for...

Fatal error: modbus.h: No such file or directory

I'm expecting a lot of difficulties to make my program working with the library libmodbus on Linux.
I've installed libmodbus with the command sudo make install and after make but the problem is when I want to link the library in my C program.
My Makefile for now is like:
all: test
test: main.o com.o
gcc main.o com.o -o test
main.o: main.c
gcc -c main.c -o main.o
com.o: com.c
gcc -c com.c -Wl,-rpath=/usr/local/lib -Wl,LIBDIR -o com.o
clean:
rm -rf *o test
In my file com.c I include the file modbus.h like this:
#include <modbus.h>
And I always get the error:
fatal error: modbus.h: No such file or directory.
If it can help when I did make install, the code return me this:
If you ever happen to want to link against installed libraries
in a given directory, LIBDIR, you must either use libtool, and
specify the full pathname of the library, or use the '-LLIBDIR'
flag during linking and do at least one of the following:
add LIBDIR to the `LD_LIBRARY_PATH' environment variable during execution
add LIBDIR to the `LD_RUN_PATH' environment variable during linking
use the `-Wl,-rpath -Wl,LIBDIR' linker flag
have your system administrator add LIBDIR to `/etc/ld.so.conf'
It seems like the modbus.h is not in the standard include directory.
You should to add the -I/<includes_path> flag to gcc options.
I suppose here:
gcc -I/<include_dir_path> -c com.c -Wl,-rpath=/usr/local/lib -Wl,LIBDIR -o com.o

FFMPEg and gcc problem

The problem is this: I wrote a simple program that uses FFMPEG. compile as follows:
gcc -lavcodec -lavformat -lavutil -c test.c
gcc -lavcodec -lavformat -Lavut -o test test.o
Compiled without problems, test file appears, but when you start:
. / test
An error occurs:
. / test: error while loading shared libraries: libavcodec.so.53: cannot open shared object file: No such file or directory
At what ffmpeg was originally built and installed and the file libavcodec.so.53 there. In what may be the problem?
You appear to be linking against libraries in a custom library directory, -Lavut.
Check where your loader looks for the executable's libraries:
ldd ./test
If any of them are in non-standard directories (and ldd indicates that a particular library couldn't be found), append those to the LD_LIBRARY_PATH:
LD_LIBRARY_PATH=/tmp/work/avut ./test
If you like, you can hardcode the library path into the executable with the -rpath linker option, e.g. gcc ... -Wl,-rpath -Wl,/tmp/work/avut.

Makefile to compile c/h?

I need to compile an old application whose tarball only contains *.c and *h, ie. no Makefile. The root directory contains the application, and a sub-directory contains a library the application needs.
My make/Makefile knowledge isn't great, and I was wondering what the easiest way would be to compile this application + library.
Thank you.
Edit: Using this script...
# cat compile.bash
#!/bin/bash
cd mylib
for cfile in *.c; do
ofile=$(echo "$cfile" | sed 's#.c$#.so#')
gcc -shared -c "$cfile" -o "$ofile"
done
cd ..
gcc *.c -I mylib -L mylib -mylib -o myapp
... I notice that each *.c file in mylib/ is compiled into a *.so file instead of compiling each into an object file and building a single .so file, and I get tons of warnings and errors, eg.
unzip.c: In function âunzipâ:
unzip.c:991: warning: format not a string literal and no format arguments
gcc: unrecognized option '-mylib'
file_util.c: In function âfile_moveâ:
file_util.c:98: error: âerrnoâ undeclared (first use in this function)
I don't know how to compile the library, and then compile the application without error/warning.
No need to use a for loop or generate intermediate object files:
(cd mylib && gcc -shared -fPIC -o libfoo.so *.c) && \
gcc -Imylib -o app *.c mylib/libfoo.so
Compile the library:
cd libfoo
for cfile in *.c; do
ofile=$(echo "$cfile" | sed 's#.c$#.so#')
gcc -shared -c "$cfile" -o "$ofile"
done
After this, you should have a libfoo.so file in libfoo/. Then, compile the program (Don't forget to cd back):
gcc *.c -I libfoo -L libfoo -lfoo -o application
The easiest is probably to get an IDE to do the build for you. Netbeans for one will create a Makefile so you can then build the project independently of the IDE.

Resources