我正在尝试创建一个自定义的c库,我可以使用ffi从ruby调用它。我的库将用自己的代码包装某些libtiff函数,生成的高级函数将通过ffi接口从ruby内部调用。
我用C编写了测试代码,它可以成功地编译成.so文件。我已经通过ffi将同样的代码插入到ruby中,并且可以成功地从ruby代码调用简单的函数。
但是,当我在c库代码中包含libtiff并定义一个使用libtiff例程的函数时,ruby代码在运行时抛出类似于以下的错误。

/usr/bin/ruby: symbol lookup error: /<path_to_lib>/libtiffconverter.so: undefined symbol: TIFFOpen

我猜这与编译器/链接器的工作方式有关。我对C很生疏…已经15年多没碰过了,我也不知道该怎么解决这个问题。我正在使用,代码::块IDE,并将我的代码放在动态库项目中。只要我不包括libtiff,一切都按预期进行。一旦我做了…尽管代码是编译的,但libtiff.so中的任何内容都会出现符号查找错误。
下面是生成上述错误的测试库模块代码:
#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);
    }
}

以下是编译器命令
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()通过ffi从ruby调用,工作正常。ConvertTIFF()没有。任何帮助都非常感谢。
更新1:
下面是我的自定义库的ldd输出:
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)

更新2:
下面是LDD输出,现在一切正常:
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)

最佳答案

问题
/usr/bin/ruby: symbol lookup error: /<path_to_lib>/libtiffconverter.so: undefined symbol: TIFFOpen
找不到您的TIFFOpen()使用的函数ConvertTIFF()。此函数属于libtiff库。您需要将项目链接到此库。
解决方案:链接libtiff
将选项-ltiff添加到上面的g++行,即:

g++ -shared  obj/Release/main.o  -o bin/Release/libtiffconverter.so -s -ltiff

您可以通过以下方式检查您刚刚生成的libtiffconverter.so是否实际依赖于libtiff库(它应该):
ldd libtiffconverter.so | grep  libtiff

下面是上面命令的输出示例:
libtiff.so.5 => /usr/lib/x86_64-linux-gnu/libtiff.so.5 (0x00007fda361a8000)

您可能还需要将-L选项添加到上面的g++行,然后是libtiff.so所在的目录。要获取其位置,可以执行以下操作:
find / -name 'libtiff*'

关于c - Ruby,ffi和自定义C库,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/47796477/

10-11 16:57