为什么我不能将swig包装std :: vector转换为Ruby类?

jac*_*son 28 ruby swig stl

我有一个带有嵌入式Ruby解释器的应用程序,以及与swig生成的STL类的接口.除了一件事,几乎一切都很好,这要归功于swig:

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

%inline%{
  std::vector<double> test;
%}
Run Code Online (Sandbox Code Playgroud)

当我尝试在Ruby中使用它时,类型Stuff::Vectord存在,但它不是生成的单例方法测试的返回类型.查看生成的C包装器文件,我可以看到类Vectord和它的方法被定义,但看着_wrap_test_get我没有看到返回sth类的任何东西Stuff::Vectord.

我需要做什么来test打字Vectord

lef*_*cus 3

首先,你是对的。ruby 生成的Stuff::test对象不是类型Vectord

然而,它的行为与VectordRuby 这样的鸭子类型语言最重要的问题完全相同。

对 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;
%}
Run Code Online (Sandbox Code Playgroud)

构建模块

swig 包装可以通过以下方式生成

swig -ruby -c++ Stuff.i
Run Code Online (Sandbox Code Playgroud)

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

g++ Stuff_wrap.cxx -shared -fPIC -o Stuff.so -I /usr/lib/ruby/1.8/x86_64-linux/
Run Code Online (Sandbox Code Playgroud)

使用模块

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

正如我们所看到的,返回的对象的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
Run Code Online (Sandbox Code Playgroud)

此外,它还可以直接与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]
Run Code Online (Sandbox Code Playgroud)

其他 SWIG 目标

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

结论

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

它们在 Ruby 代码内部几乎无法区分。生成的代码完全符合您的要求。