2013-07-23 26 views
2

我想在Ruby 2.0中使用ffi gem加載自定義C++函數。當在IRB會議裝載我的自定義庫我的attach_function通話過程中有一個錯誤:爲什麼Ruby FFI不附加自定義共享對象庫中的函數

FFI::NotFoundError: Function 'add' not found in [/usr/local/lib/libbridge.so] 

這裏是我創建並檢查了我的libbridge共享對象的方式:

我得到了我的庫中的頭文件:

文件:bridge.h

std::string fooBar(std::string bar); 
int add(int a, int b); 

的庫實現:

文件:bridge.cpp

#include <iostream> 

std::string fooBar(std::string bar) 
{ 
    return "foo" + bar; 
} 

int add(int a, int b) 
{ 
    return a + b; 
} 

爲此,我對我的新庫鏈接二進制代碼:

文件:bridger.cpp

#include <iostream> 
#include "bridge.h" 

int main(int argc, char* argv[]) 
{ 
    std::string foobar = fooBar("barrrr"); 
    std::cout << foobar << "\n"; 

    std::cout << "Adding 4 and 2: " << add(4,2) << "\n"; 
} 

首先,我編譯我的lib添加到對象代碼:

$ g++ -c -Wall -Werror -fpic bridge.cpp 

然後我使它的共享對象:

$ g++ -shared -o libbridge.so bridge.o 

我剝調試符號:

$ strip -o libbridge.so libbridge.so 

,並將其移動到我的系統:

$ sudo mv libbridge.so /usr/local/lib/ 

然後我讓可執行文件,並運行ldconfig:

$ sudo chmod 0755 /usr/local/lib/libbridge.so 
$ sudo ldconfig 

短檢查:

$ ldd /usr/local/lib/libbridge.so 
    linux-gate.so.1 => (0xb7781000) 
    libstdc++.so.6 => /usr/lib/i386-linux-gnu/libstdc++.so.6 (0xb7689000) 
    libm.so.6 => /lib/i386-linux-gnu/i686/cmov/libm.so.6 (0xb7663000) 
    libgcc_s.so.1 => /lib/i386-linux-gnu/libgcc_s.so.1 (0xb7645000) 
    libc.so.6 => /lib/i386-linux-gnu/i686/cmov/libc.so.6 (0xb74e2000) 
    /lib/ld-linux.so.2 (0xb7782000) 

我從我的工作目錄中刪除的語言環境版本:

$ rm -f bridge.so 
$ rm -f bridge.o 

我編譯我的二進制:

$ g++ -Wall -o bridger bridger.cpp -lbridge 

我成功地執行它,得到的輸出我的預期:

$ ./bridger 
foobarrrr 
Adding 4 and 2: 6 

現在我創建一個紅寶石模塊ffi_test.rb:

require "ffi" 
module FfiTest 

    extend FFI::Library 
    ffi_lib_flags :now, :global 
    ffi_lib "/usr/local/lib/libbridge.so" 
    attach_function :add, [:int, :int], :int 
    attach_function :fooBar, [:string], :string 

end 

當我在IRB會議加載代碼現在我總是得到這個錯誤:

$ irb 
2.0.0p247 :001 > load "ffi_test.rb" 
FFI::NotFoundError: Function 'add' not found in [/usr/local/lib/libbridge.so] 
    from /home/me/.rvm/gems/[email protected]/gems/ffi-1.9.0/lib/ffi/library.rb:251:in `attach_function' 
    from ffi_test.rb:8:in `<module:EricInterface>' 
    from ffi_test.rb:3:in `<top (required)>' 
    from (irb):1:in `load' 
    from (irb):1 
    from /home/me/.rvm/rubies/ruby-2.0.0-p247/bin/irb:16:in `<main>' 

我不明白,這裏的問題是什麼。我的庫顯然會導出:add和:fooBar函數,否則我的橋接器二進制文件將無法成功鏈接到此庫。 Ruby ffi反而無法看到並掛載這些函數。

任何人都可以在這裏指出我正確的方向嗎?

問候 菲利克斯

回答

3

FFI期待一個C函數,所以它沒有找到,因爲名字改編C++做你的C++函數。

你需要告訴鏈接,使功能從C訪問,例如,通過這樣做(在您的.h)文件中

extern "C" { 
    int add(int a, int b); 
} 

我懷疑FFI也將不知道如何處理的功能做到這一點期待爲std :: string作爲參數

+0

嘿弗雷德裏克,感謝您的提示。我完全從頭文件和源文件中刪除了函數fooBar。將你的行添加到我的頭文件中,重新編譯並重新安裝這個庫。但錯誤仍然是一樣的。 – GeorgieF

+0

當我將bridge.cpp重命名爲bridge.c並使用gcc而不是g ++時,我得到了這個工作。但我真正想要使用的預期目標庫是C++。那我該如何利用它呢? FFI不支持C++嗎? – GeorgieF

+0

你的bridge.cpp包含bridge.h嗎? –

0

在OSX,什麼工作對我來說是-dynamiclib編譯:

g++ -dynamiclib -o mylib.dylib mylib.cpp