为什么Google的Cityhash gem不会安装?

时间:2011-07-11 22:52:21

标签: ruby macos ffi murmurhash

我正在尝试使用Ruby的FFI附加到Google cityhash gem;它是一个64位,128位非加密哈希,类似于默认的Ruby哈希函数(murmur_hash 1),但是更新一点,更重要的是,允许在哈希上设置种子。

我使用Mac上的默认/usr/local/lib将cityhash安装到./configure。 这会将一些库放在/usr/local/lib

-rwxr-xr-x 1 root wheel 13720 Jul 11 15:16 /usr/local/lib/libcityhash.0.dylib
-rw-r--r-- 1 root wheel 43424 Jul 11 15:16 /usr/local/lib/libcityhash.a
lrwxr-xr-x 1 root wheel    19 Jul 11 15:16 /usr/local/lib/libcityhash.dylib -> libcityhash.0.dylib
-rwxr-xr-x 1 root wheel   977 Jul 11 15:16 /usr/local/lib/libcityhash.la

我使用的是Mac OS X. gcc版本是4.6,它不是默认的Mac gcc,但我也尝试过。

ruby 1.9.2p180 (2011-02-18 revision 30909) [x86_64-darwin10.6.0]

ffi(在mac上安装默认gcc,gcc 4.6不起作用?)

我制作了最简单的模块:

require 'ffi'
module MyCityHash
  extend FFI::Library

  ffi_lib 'cityhash'
  attach_function  :CityHash64,  [:string, :size_t], :uint64    
end

但是当我尝试将此模块包含到任何Ruby类或脚本文件中时,我收到错误:

/Users/charlesmartin/.rvm/gems/ruby-1.9.2-p180/gems/ffi-1.0.9/lib/ffi/library.rb:147:in `attach_function': Function 'CityHash64' not found in [libcityhash.dylib] (FFI::NotFoundError)

CityHash64在city.h中有签名:

uint64 CityHash64(const char *buf, size_t len);

我非常感谢有关如何调试此内容的任何见解。

1 个答案:

答案 0 :(得分:3)

从快速浏览cityhash项目看,它看起来像是C ++,这意味着它们不能作为C符号显示。名称将被破坏(如果你运行'nm libcityhash.dylib',你可以看到这个。)

您有几个选择:

  1. 计算出损坏的名称(使用nm或objdump),并将它们用作attach_function的本机函数名称。 e.g。

    attach_function :CityHash64, :__Z10CityHash64PKcm, [ :string, :size_t ], :uint64
    

    其中“__Z10CityHash64PKcm”是CityHash64的符号名称,如nm所示(注意:平台之间的错位名称不同)。 attach_function的第一个arg是你希望它可以从ruby调用的名称,所以你仍然可以将它称为MyCityHash.CityHash64()。

  2. 通过使用'extern“C”'为要访问的每个函数添加前缀,将cityhash函数公开为C符号(因此对ruby-ffi可见)。 e.g。

    extern "C" uint64 CityHash64(const char *buf, size_t len);
    
  3. 然后重建libcityhash.dylib。

    如果您要创建一个gem以分发给其他人,那么您将不得不使用选项#1,除非您可以说服cityhash维护者将这些函数公开给普通的旧C。