2015-09-21 46 views
4

我正在使用SWIG爲一些C++類創建一個Ruby包裝器。這是這是給我找麻煩了C++方法的簽名:SWIG:映射typedef的數組

virtual LogP wordProb(VocabIndex word, const VocabIndex *context); 

這是VocabIndex的定義:

#ifdef USE_SHORT_VOCAB 
typedef unsigned short VocabIndex; 
#else 
typedef unsigned int VocabIndex; 
#endif 

這是我從Ruby腳本調用的方式:

index = 8 
context = [index] 
puts ngram.wordProb(index, context) 

這是我得到的錯誤,當我運行我的腳本:

ngram.rb:26:in `wordProb': Expected argument 2 of type VocabIndex const *, but got Array [8] (TypeError) 
    in SWIG method 'wordProb' 
    from ngram.rb:26:in `<main>' 

我嘗試的解決方案

看完後的docs(是的,我使用痛飲2.0),我在.i文件試過這樣:

%module rubylm 

%{ 
#include "srilm-1.7.1/lm/src/Ngram.h" 
%} 

%include "srilm-1.7.1/lm/src/Counts.h" 
%include "srilm-1.7.1/lm/src/Ngram.h" 
%include "typemaps.i" 

virtual LogP Ngram::wordProb(VocabIndex word, const VocabIndex *INPUT); 

的痛飲命令運行正常,但是當我試圖建立的包裝庫,我得到這個:

NgramWrapper_wrap.cxx:148:17: fatal error: tcl.h: No such file or directory 
#include <tcl.h> 

所以我啓動了一個終端(這是一個Ubuntu盒),跑:

sudo apt-get install tcl-dev 

安裝了tcl 8.6,它將頭文件放在/usr/include/tcl8.6目錄中。所以,我補充說,包括Makefile行它建立NgramWrapper_wrap.o目錄:

NgramWrapper_wrap.o: NgramWrapper_wrap.cxx 
    $(CC) $(CFLAGS) NgramWrapper_wrap.cxx -I $(RUBY_SRC) -I $(MISC_INCLUDE) -I $(DSTRUCT_INCLUDE) -I /usr/include/tcl8.6 

不過,我仍然得到編譯錯誤。這裏是我被困住的地方:

NgramWrapper_wrap.cxx:10812:34: error: ‘RARRAY_LEN’ was not declared in this scope 
    int size = RARRAY_LEN(objv[3]); 
           ^
NgramWrapper_wrap.cxx:10816:5: error: ‘VALUE’ was not declared in this scope 
    VALUE *ptr = RARRAY_PTR(objv[3]); 
    ^
NgramWrapper_wrap.cxx:10816:12: error: ‘ptr’ was not declared in this scope 
    VALUE *ptr = RARRAY_PTR(objv[3]); 
      ^
NgramWrapper_wrap.cxx:10816:36: error: ‘RARRAY_PTR’ was not declared in this scope 
    VALUE *ptr = RARRAY_PTR(objv[3]); 
            ^
NgramWrapper_wrap.cxx:10819:35: error: ‘StringValuePtr’ was not declared in this scope 
     arg3[i]= StringValuePtr(*ptr); 
           ^
NgramWrapper_wrap.cxx: In function ‘int _wrap_NgramCountWrapper_run(ClientData, Tcl_Interp*, int, Tcl_Obj* const*)’: 
NgramWrapper_wrap.cxx:10908:34: error: ‘RARRAY_LEN’ was not declared in this scope 
    int size = RARRAY_LEN(objv[3]); 
           ^
NgramWrapper_wrap.cxx:10912:5: error: ‘VALUE’ was not declared in this scope 
    VALUE *ptr = RARRAY_PTR(objv[3]); 
    ^
NgramWrapper_wrap.cxx:10912:12: error: ‘ptr’ was not declared in this scope 
    VALUE *ptr = RARRAY_PTR(objv[3]); 
      ^
NgramWrapper_wrap.cxx:10912:36: error: ‘RARRAY_PTR’ was not declared in this scope 
    VALUE *ptr = RARRAY_PTR(objv[3]); 
            ^
NgramWrapper_wrap.cxx:10915:35: error: ‘StringValuePtr’ was not declared in this scope 
     arg3[i]= StringValuePtr(*ptr); 

我能想到的是Ruby,Swig和Tcl之間的一些版本不匹配。但是我怎麼知道使用哪個Tcl版本?我搜索文檔無濟於事...

+1

Carrays.i是快速解決方案:http://www.swig.org/Doc2.0/Library.html#Library_carrays更多的紅寶石知識比我有更聰明的做法。 – Flexo

+0

如果我嘗試使用carrays。我,當我嘗試使用typemaps.i時遇到了相同的構建錯誤。我的Ruby-Swig-Tcl組合中有些問題。我現在所能想出的就是降級Tcl。要嘗試一下。 –

回答

2

嗯。

我只是做了以下

vocal.i

%module rubylm 

%{ 
#include "Ngram.h" 
%} 

%include "Ngram.h" 
%include "typemaps.i" 

virtual LogP Ngram::wordProb(VocabIndex word, const VocabIndex *INPUT); 

Ngram.h

#pragma once 

#ifdef USE_SHORT_VOCAB 
typedef unsigned short VocabIndex; 
#else 
typedef unsigned int VocabIndex; 
#endif 

typedef int LogP; 

class NGram { 
public: 
    LogP wordProb(VocabIndex word, const VocabIndex *context); 
}; 

命令執行

swig2.0 -ruby -c++ vocal.i

FO通過

g++ -c vocal_wrap.cxx -I/usr/include/ruby-2.1.0 -I/usr/include/x86_64-linux-gnu/ruby-2.1.0

llowed沒有任何錯誤。你忘了-C++選項,爲什麼你需要tcl.h

+0

當I%包含'typemaps.i'或'carrays.i'時,Tcl依賴關係就會出現。如果我查看生成的代碼,在開頭就有這行:'#define SWIGTCL'。 -C++選項總是存在,我正在使用Makefile。順便說一下,你使用的是ruby 2.1.0,而我正在使用1.9.3。這可能是一個問題嗎? –

+0

也許吧。我想我會瀏覽包含的標題,看看是否有一些缺失的定義。記住SWIG不會遞送標題。也可能是包含錯誤的typemaps.i。 –

+0

我會在今晚檢查我生成的代碼 –