【问题标题】:Ruby, ffi, and a custom C libraryRuby、ffi 和自定义 C 库
【发布时间】:2018-05-27 13:07:21
【问题描述】:

我正在尝试创建一个可以使用 FFI 从 Ruby 调用的自定义 C 库。我的库将使用我自己的代码包装某些 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 年多没碰过它了,我不知道该怎么做才能解决这个问题。我正在使用 Code::Blocks 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)

【问题讨论】:

  • 我想我找到了问题所在:问题出在g++ 行,而不是gcc 行。我已经更新了答案。

标签: c ruby linux gcc ffi


【解决方案1】:

问题

/usr/bin/ruby: symbol lookup error: /&lt;path_to_lib&gt;/libtiffconverter.so: undefined symbol: TIFFOpen

找不到您的ConvertTIFF() 使用的函数TIFFOpen()。此函数属于 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*'

【讨论】:

  • 这没有帮助。两个都试过了:“gcc -Wall -O2 -fPIC -ltiff -I/usr/lib/x86_64-linux-gnu -I/usr/include/x86_64-linux-gnu -c //main.c -o obj /Release/main.o”和“gcc -Wall -O2 -fPIC -L /usr/lib/x86_64-linux-gnu/libtiff.so -I/usr/lib/x86_64-linux-gnu -I/usr/include /x86_64-linux-gnu -c //main.c -o obj/Release/main.o" 编译正常但同样的错误。
  • 抱歉,这也没用。我尝试了两种方式,在目录末尾有和没有 libtiff.so:“gcc -Wall -O2 -fPIC -ltiff -L /usr/lib/x86_64-linux-gnu/ -I/usr/lib/ x86_64-linux-gnu -I/usr/include/x86_64-linux-gnu -c //main.c -o obj /Release/main.o"
  • 从我正在运行 ruby​​ 脚本的同一命令行: echo $LIBRARY_PATH /usr/lib/x86_64-linux-gnu/... 所以是的,它在路径中,但无论是is not 似乎没有什么不同。
  • @Andrew 对不起,我的意思是LD_LIBRARY_PATH
  • 您上次更新成功。 g++ 行上的 -ltiff 成功了。我不需要 -L 选项。非常感谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-03-12
  • 1970-01-01
  • 2012-06-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多