我正在使用SWIG为一些C ++类创build一个Ruby Wrapper。 这是给我麻烦的C ++方法的签名:
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>'
我的尝试解决scheme :
在阅读文档 (是的,我正在使用SWIG 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);
swig命令运行良好,但是当我试图构build包装库时,我得到了这个:
NgramWrapper_wrap.cxx:148:17: fatal error: tcl.h: No such file or directory #include <tcl.h>
所以我启动了一个terminal(这是一个Ubuntu的盒子),跑了:
sudo apt-get install tcl-dev
这个安装了tcl 8.6,它的头文件放在/usr/include/tcl8.6
目录下。 所以我在构buildNgramWrapper_wrap.o的Makefile行中添加了include目录:
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版本呢? 我search了文档无济于事
嗯。
我只是做了以下
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
其次是
g++ -c vocal_wrap.cxx -I/usr/include/ruby-2.1.0 -I/usr/include/x86_64-linux-gnu/ruby-2.1.0
没有任何错误。 你忘了-c ++选项,为什么你需要tcl.h