SWIG (v1.3.29) generated C++ to Java Vector class not acting properly
我有一些本地的C++代码,我使用SWIG将其转换成Java,这样我的Java应用程序就可以使用它。特别是有一些函数返回std::vector。以下是我的界面文件的一个片段:
1 2 3 4 5 6 7 | %include"std_vector.i" namespace std { %template(Vector) vector<double>; %template(Matrix) vector<vector<double> >; } %include"std_string.i" |
我使用的swig版本中包含了
在Java中封装EDCOX1×0的适当基类型是EDOCX1×1。使用
SWIG没有为你这样做的原因是因为你不能在Java中拥有EDCOX1×5,它必须是EDCOX1×5(EDCOX1,7)继承自EDCOX1,8,而EDCOX1(7)是原始类型。
我已经讲了一个小例子,它封装了EDCOX1、10和EDCOX1,11在Java中很好地封装。它不是完整的,但是它支持Java和EDCOX1中的"每种"迭代方式,在元素上使用12Ω/EDCOX1×13Ω。它应该足以说明如何在需要的时候实现其他事情。
我将在接下来的部分中讨论接口文件,但基本上,它都是连续的和完整的。
从定义我们的模块
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | %module num %{ #include <vector> #include <stdexcept> std::vector<double> testVec() { return std::vector<double>(10,1.0); } std::vector<std::vector<double> > testMat() { return std::vector<std::vector<double> >(10, testVec()); } %} %pragma(java) jniclasscode=%{ static { try { System.loadLibrary("num"); } catch (UnsatisfiedLinkError e) { System.err.println("Native code library failed to load. " + e); System.exit(1); } } %} |
我们有用于生成的
在EDCOX1的18个方面也有一个窍门,我喜欢在Java SWIG接口中使用,以使共享对象/ DLL透明地为接口的用户加载。
接口文件的下一个部分是我们想要包装的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | namespace std { template<class T> class vector { public: typedef size_t size_type; typedef T value_type; typedef const value_type& const_reference; %rename(size_impl) size; vector(); vector(size_type n); size_type size() const; size_type capacity() const; void reserve(size_type n); %rename(isEmpty) empty; bool empty() const; void clear(); void push_back(const value_type& x); %extend { const_reference get_impl(int i) throw (std::out_of_range) { // at will throw if needed, swig will handle return self->at(i); } void set_impl(int i, const value_type& val) throw (std::out_of_range) { // at can throw self->at(i) = val; } } }; } |
这里的主要变化是
接下来,在接口文件中,我们告诉我们要实现的基类和接口,以及编写一些额外的Java代码来强制不兼容类型的函数之间的事物:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | %typemap(javabase) std::vector<double>"java.util.AbstractList<Double>" %typemap(javainterface) std::vector<double>"java.util.RandomAccess" %typemap(javacode) std::vector<double> %{ public Double get(int idx) { return get_impl(idx); } public int size() { return (int)size_impl(); } public Double set(int idx, Double d) { Double old = get_impl(idx); set_impl(idx, d.doubleValue()); return old; } %} %typemap(javabase) std::vector<std::vector<double> >"java.util.AbstractList<Vector>" %typemap(javainterface) std::vector<std::vector<double> >"java.util.RandomAccess" %typemap(javacode) std::vector<std::vector<double> > %{ public Vector get(int idx) { return get_impl(idx); } public int size() { return (int)size_impl(); } public Vector set(int idx, Vector v) { Vector old = get_impl(idx); set_impl(idx, v); return old; } %} |
这为EDOCX1的10和30的EDOCX1的一个基类设置了EDCOX1,11为32(EDCOX1,34)是我们在接口的Java端调用EDOCX1 10。
我们还提供了一个在Java端实现EDCOX1 36和EDCOX1 37的实现,它可以处理EDCOX1 7对EDCOX1、7、7的转换和返回。
最后,我们在界面中添加了:
1 2 3 4 5 6 7 | namespace std { %template(Vector) std::vector<double>; %template(Matrix) std::vector<vector<double> >; } std::vector<double> testVec(); std::vector<std::vector<double> > testMat(); |
这告诉Swig将
下一步,EDCOX1〔44〕,一个简单的EDCOX1(45)在Java中执行我们的代码有点:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | import java.util.AbstractList; public class test { public static void main(String[] argv) { Vector v = num.testVec(); AbstractList<Double> l = v; for (Double d: l) { System.out.println(d); } Matrix m = num.testMat(); m.get(5).set(5, new Double(5.0)); for (Vector col: m) { for (Double d: col) { System.out.print(d +""); } System.out.println(); } } } |
要构建和运行此功能,我们需要:
1 2 3 4 | swig -java -c++ num.i g++ -Wall -Wextra num_wrap.cxx -shared -I/usr/lib/jvm/java-6-sun/include -I/usr/lib/jvm/java-6-sun/include/linux/ -o libnum.so javac test.java && LD_LIBRARY_PATH=. java test |
我在Linux/x86上用G++4.4版和Swig 1.3.40测试了这一点。
完整版本的
我没有从
我是那个在这个问题上慷慨大方的人,因为我也有同样的问题。我有点不好意思报告我终于找到了真正的解决方案——它在swig手册中!修复方法是在编译生成的代码时使用
问题在于,最近版本的