Почему Google Cityhash gem не устанавливается? - PullRequest
2 голосов
/ 12 июля 2011

Я пытаюсь использовать FFI в Ruby для подключения к гему Google cityhash;Это 64-битный и 128-битный некриптографический хэш, похожий на хэш-функцию Ruby по умолчанию (murmur_hash 1), но он немного новее и, что более важно, позволяет установить начальное значение для хеша.

Я установил cityhash в /usr/local/lib, используя ./configure по умолчанию на моем Mac.Это помещает некоторые библиотеки в /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 (установлен с gcc по умолчанию на mac, 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 Ответ

3 голосов
/ 12 июля 2011

Если взглянуть на проект cityhash, он выглядит как C ++, что означает, что они не видны как символы C.Имена будут искажены (вы можете увидеть это, если запустите 'nm libcityhash.dylib').

У вас есть несколько вариантов:

  1. искаженные имена (с использованием nm или objdump) и используют их в качестве имени собственной функции для attach_function.например,

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

    , где "__Z10CityHash64PKcm" - это имя символа CityHash64, как показано в нм (примечание: искаженное имя различается для разных платформ).Первым аргументом attach_function является имя, которое вы хотите, чтобы оно вызывалось как от ruby, поэтому вы все равно должны называть его MyCityHash.CityHash64 ().

  2. Предоставить функции cityhash в виде символов C(и, следовательно, видимый для ruby-ffi), добавляя префикс каждой функции, к которой вы хотите получить доступ, с помощью 'extern "C"'.например,

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

Затем пересоберите libcityhash.dylib.

Если вы создаете гем для распространения среди других, вам придется использовать опцию # 1, если только вы не можете убедить сопровождающих ситхеша выставить функции простому старому C.

...