为什么我无法将swig包装的std :: vector传递给Ruby类?

29

我有一个集成了Ruby解释器并与由swig生成的STL类接口交互的应用程序。 由于swig的帮助,几乎所有东西都工作得很好,除了一件事情:

%module Stuff
%import "std_vector.i"
namespace std
{
  %template(Vectord) vector<double>;
}; 

%inline%{
  std::vector<double> test;
%}
当我尝试在Ruby中使用这个方法时,类型Stuff::Vectord是存在的,但它不是生成的单例方法test的返回类型。查看生成的C包装文件,我可以看到类Vectord及其方法被定义,但查看_wrap_test_get,我没有看到任何返回类Stuff :: Vectord sth
我该怎么做才能将test的类型设置为Vectord

2
我已经使用您的示例进行了工作,并且在生成Ruby或C#输出方面没有任何问题。确实,您在test()函数的swig生成输出中看不到任何特殊的Vectord类型,但它返回了正确的类型。我已经学会了使用C#进行测试并探索*.cs包装器中使用的类型,这可以对您的SWIG代码进行良好的健全性检查。 - lefticus
1个回答

3

首先,你是正确的。Ruby生成的Stuff::test对象不属于Vectord类型。

然而,它属于与Vectord完全相似的类型,在像Ruby这样的鸭子类型语言中,这是最重要的问题。

对Stuff.i的更正

在你的示例中有一个小问题。 %import <stl_vector.i>语句应该是%include <stl_vector.i>

正确的完整示例如下:

%module Stuff
%include "std_vector.i"
namespace std
{
  %template(Vectord) vector<double>;
}; 

%inline%{
  std::vector<double> test;
%}

构建模块

可以使用以下命令生成swig包装器:

swig -ruby -c++ Stuff.i

使用以下语句(用g++编译):

g++ Stuff_wrap.cxx -shared -fPIC -o Stuff.so -I /usr/lib/ruby/1.8/x86_64-linux/

使用该模块

jason@jason-VirtualBox:~$ irb
irb(main):001:0> require 'Stuff'
=> true
irb(main):003:0> Stuff::test.class
=> Array

我们可以看到,Stuff::test返回的对象类型是Array。然而,与普通的Ruby数组不同,这个数组只能被设置为可转换为std::vector<double>的值。
irb(main):002:0> Stuff::test = [5,4,3]
=> [5, 4, 3]
irb(main):003:0> Stuff::test = [5.0, "5.0"]
TypeError: double
    from (irb):3:in `test='
    from (irb):3
    from :0

此外,它可以直接转换为std::vector<double>对象。
irb(main):002:0> vec = Stuff::Vectord.new()
=> std::vector<double,std::allocator< double > > []
irb(main):003:0> vec << 5.0
=> 5.0
irb(main):004:0> vec << 2.3
=> 2.3
irb(main):005:0> vec
=> std::vector<double,std::allocator< double > > [5.0,2.3]
irb(main):006:0> Stuff::test = vec
=> std::vector<double,std::allocator< double > > [5.0,2.3]
irb(main):007:0> vec2 = Stuff::Vectord.new(Stuff::test)
=> std::vector<double,std::allocator< double > > [5.0,2.3]
irb(main):008:0> Stuff::test.class
=> Array
irb(main):009:0> vec2.class
=> Stuff::Vectord
irb(main):010:0> Stuff::test
=> [5.0, 2.3]

其他 SWIG 目标

需要注意的是,C# 和 Java 这两个静态类型的 SWIG 目标产生了您所期望的结果。如果您对 SWIG 的输出如何处理您的类型有任何疑问,将 C# 或 Java 输出与您所期望的进行比较几乎总是一个好主意。

结论

虽然 Stuff::testVectord 是两种不同的类型,但它们都是只能存储双精度浮点数的数组。

在 Ruby 代码中,它们几乎无法区分。生成的代码完全按照您的要求执行。


你说你把%import改成了%include,但是“正确的完整示例”仍然显示%import。那是疏忽吗? - Flexo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接