Подтвердить что ты не робот

Почему я не могу получить swig wrap std::vector для класса Ruby?

У меня есть приложение со встроенным интерпретатором Ruby и сопряжено с классами STL, сгенерированными swig. Почти все получилось отлично благодаря swig, за исключением одного:

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

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

Когда я пытаюсь использовать это в Ruby, тип Stuff::Vectord существует, но это не тип возвращаемого значения метода сгенерированного однотонального метода. Глядя на сгенерированный файл оболочки C, я могу видеть класс Vectord и его методы, определяемые, но глядя на _wrap_test_get, я не вижу ничего возвращаемого sth класса Stuff::Vectord.

Что мне нужно сделать, чтобы получить test в качестве Vectord?

4b9b3361

Ответ 1

Во-первых, вы правы. Созданный 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/

Использование модуля

[email protected]:~$ 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

Важно отметить, что статически типизированные цели SWIG для С# и Java дают ожидаемые результаты. Если у вас когда-либо возник вопрос о том, как обрабатываются ваши типы в выводе SWIG, почти всегда стоит сравнивать вывод С# или Java с тем, что вы ожидаете.

Заключение

Хотя Stuff::test и Vectord - два разных типа, они оба являются массивами, которые могут хранить только удвоения.

Они почти неотличимы внутри кода Ruby. Созданный код делает именно то, что вы хотите.