Вопрос

Я использую SWIG, чтобы обернуть сценарий Ruby вокруг библиотеки C++.В Ruby я могу наследовать класс C++, но не могу передать полученный указатель на функцию C++ полиморфным способом.

Вот конкретный пример.Файл интерфейса SWIG определяет базовый класс Animal с виртуальной функцией sound():

[animals.i]
%module(directors="1") animals
%{
#include "animals.h"
%}

// Apply the 'director' feature to a virtual function,
// so that we can override it in Ruby.
%feature("director") Animal::sound;
class Animal {
public:
    Animal();
    virtual ~Animal();
    virtual void sound();
};

class Dog : public Animal {
public:
    Dog();
    virtual ~Dog();
    virtual void sound();
};

// This function takes an Animal* and calls its virtual function sound().
void kick(Animal*, int);   

Обратите внимание, что я использую директора SWIG для межъязыкового полиморфизма, но, похоже, это не работает.Сценарий Ruby выглядит следующим образом:

[tst.rb]
require 'animals'
include Animals

dog= Dog.new   # Instantiate C++ class
kick(dog, 3)   # Kick the dog 3 times => It barks 3 times.
               # So far so good.

class Cat < Animal   # Inherit from a C++ class
   def initialize
      puts "Creating new cat"
   end

   def sound
      puts "Meow"
   end
end

cat= Cat.new   # Instantiate Ruby class

kick(cat, 9)   # This does not fly.

Последняя строка сценария выдает следующую ошибку:

Expected argument 0 of type Animal *, but got Cat #<Cat:0xb7d621c8>

Каким-то образом SWIG не позволяет мне рассматривать объект Ruby как указатель на Animal.Есть идеи?

Это было полезно?

Решение

Я получил решение своей проблемы от Тобиаса Гримма в списке рассылки swig-user.Первая часть проблемы — это вводящее в заблуждение сообщение об ошибке SWIG.Похоже, что сообщение предполагает, что я передаю неправильный тип указателя на мою функцию C ++, но это не так.Если вы проверите класс исключения в Ruby, он является объективным удалением, а это означает, что основной указатель C -структуры моего класса CAT является нулевым.Таким образом, реальная проблема заключается в том, что указатель нулевой, а не то, что у него неправильный тип.

Указатель нуль, потому что я просто забыл назвать «супер» в методе инициализации Cat.Таким образом, с созданием кошки, основной C -структуры, распределяется, потому что конструктор животных никогда не вызывается.Забыть называть «Super»-очень распространенная ошибка Ruby-Beginner, особенно для таких людей, как я, которые приезжают из C ++, которые привыкли к автоматическому цепочке конструкторов.

Итак, все, что мне нужно было сделать, это добавить вызов «super»:

class Cat < Animal   # Inherit from a C++ class
   def initialize
      puts "Creating new cat"
      super()
   end
   def sound
      puts "Meow"
   end
end

Теперь это работает нормально.Спасибо, Тобиас.

Другие советы

Я считаю, что вам нужно определить вспомогательная функция который возвращает указатель на ваш экземпляр.Я использовал только указатели с fopen, поэтому не знаю, действительно ли это будет работать или мне чего-то не хватает.Удачи!

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top