I’m trying to create a custom C library I can call from Ruby using FFI. My library will wrap certain libtiff functions with my own code, and the resulting higher-level functions will be called from within Ruby via the FFI interface.
I’ve got test code working in C, that compiles successfully to a .so file. I’ve got that same code plumbed into Ruby via FFI, and can successfully call simple functions from ruby code.
However, when I include libtiff in my C library code and define a function that uses some of the libtiff routines, the ruby code throws errors similar to the following at runtime.
/usr/bin/ruby: symbol lookup error: /<path_to_lib>/libtiffconverter.so: undefined symbol: TIFFOpen
My guess is this has something to do with the way the compiler/linker is doing things. I’m very rusty with C… haven’t touched it in 15+ years, and I’m not sure exactly what to do to resolve the problem. I’m using, the Code::Blocks IDE, and have my code in a dynamic library project. As long as I don’t include libtiff, everything works as expected. Once I do… though the code compiles, I get symbol lookup errors for anything in libtiff.so.
Here’s my test library module code that generates the above error:
#include "tiffio.h" int AddInt(int i1, int i2) { return i1 + i2; } void ConvertTIFF() { TIFF* tif = TIFFOpen("test0.tiff", "r"); if (tif) { uint32 imagelength; tdata_t buf; uint32 row; TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &imagelength); buf = _TIFFmalloc(TIFFScanlineSize(tif)); for (row = 0; row < imagelength; row++) TIFFReadScanline(tif, buf, row, 0); _TIFFfree(buf); TIFFClose(tif); } }
Here are the compiler commands
gcc -Wall -O2 -fPIC -I/usr/lib/x86_64-linux-gnu -I/usr/include/x86_64-linux-gnu -c /<path_to_source>/main.c -o obj/Release/main.o g++ -shared obj/Release/main.o -o bin/Release/libtiffconverter.so -s
AddInt()
called from ruby via FFI, works just fine. ConvertTIFF()
does not. Any help is much appreciated.
UPDATE 1:
Here’s the ldd output of my custom library:
bridge:~/tmp/tmp$ ldd libtiffconverter.so linux-vdso.so.1 => (0x00007ffd20db8000) libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f4c9a84e000) /lib64/ld-linux-x86-64.so.2 (0x000055a601577000)
UPDATE 2:
Here’s the ldd output now that things are working:
bridge:~/tmp/tmp$ ldd libtiffconverter.so linux-vdso.so.1 => (0x00007ffff4db7000) libtiff.so.5 => /usr/lib/x86_64-linux-gnu/libtiff.so.5 (0x00007fabcbea4000) libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fabcbacb000) liblzma.so.5 => /lib/x86_64-linux-gnu/liblzma.so.5 (0x00007fabcb8a8000) libjbig.so.0 => /usr/lib/x86_64-linux-gnu/libjbig.so.0 (0x00007fabcb69a000) libjpeg.so.8 => /usr/lib/x86_64-linux-gnu/libjpeg.so.8 (0x00007fabcb441000) libz.so.1 => /lib/x86_64-linux-gnu/libz.so.1 (0x00007fabcb226000) libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007fabcaf1d000) /lib64/ld-linux-x86-64.so.2 (0x000056320a73f000) libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007fabcad19000)
Advertisement
Answer
The Problem
/usr/bin/ruby: symbol lookup error: /<path_to_lib>/libtiffconverter.so: undefined symbol: TIFFOpen
The function TIFFOpen()
used by your ConvertTIFF()
is not found. This function belongs to the LibTIFF library. You need to link your project against this library.
The Solution: Linking against LibTIFF
Add the option -ltiff
to your g++
line above, i.e.:
g++ -shared obj/Release/main.o -o bin/Release/libtiffconverter.so -s -ltiff
You can check whether your just generated libtiffconverter.so
actually depends on the LibTIFF library (it should) this way:
ldd libtiffconverter.so | grep libtiff
The following is an example output of the command above:
libtiff.so.5 => /usr/lib/x86_64-linux-gnu/libtiff.so.5 (0x00007fda361a8000)
You may also need to add the -L
option to the g++
line above followed by the directory where your libtiff.so
is located. In order to obtain its location you can do the following:
find / -name 'libtiff*'