Skip to content
Advertisement

Ruby, ffi, and a custom C library

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*'
User contributions licensed under: CC BY-SA
5 People found this is helpful
Advertisement