Domanda

Io uso SWIG per avvolgere uno script di Ruby intorno una libreria C ++. In rubino, posso ereditare da una classe C ++, ma non posso passare il puntatore risultante a una funzione C ++ in modo polimorfo.

Ecco un esempio concreto. Il file di interfaccia SWIG definisce Animal classe di base con il suono funzione virtuale ():

[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);   

Si noti che uso direttori SWIG per il polimorfismo cross-language, ma questo non sembra funzionare. Lo script di Ruby si presenta così:

[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.

L'ultima riga nello script genera questo errore:

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

Così in qualche modo SWIG non mi permette di trattare l'oggetto di Ruby come un animale puntatore a. Tutte le idee?

È stato utile?

Soluzione

Ho una soluzione al mio problema da Tobias Grimm alla mailing list sorso-user. La prima parte del problema è messaggio di errore fuorviante di SWIG. Il messaggio sembra suggerire che passo il tipo sbagliato di puntatore alla mia C ++ funzione, ma questo non è il caso. Se si seleziona la classe di eccezione in rubino, è ObjectPreviouslyDeleted, il che significa che il puntatore C struct sottostante della mia classe Cat è nullo. Quindi il vero problema è che il puntatore è NULL, non che ha il tipo sbagliato.

Il puntatore è NULL perché ho semplicemente dimenticato di chiamare "super" in inizializzazione del gatto () metodo. In questo modo, con la creazione di Cat C sottostante struct viene allocato, poiché il costruttore degli animali non viene mai chiamato. Dimenticando di chiamare 'super' è errore molto comune Ruby-principianti, in particolare per le persone come me che vengono da C ++, che sono abituati a catena automatica costruttore.

Quindi, tutto quello che dovevo fare era aggiungere una chiamata al 'super':

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

Questa ora funziona benissimo. Grazie, Tobias.

Altri suggerimenti

Credo che è necessario definire un che i rendimenti un puntatore all'istanza. Ho usato solo puntatori con fopen, quindi non so se questo sarà realmente funzionare, o se c'è qualcos'altro che mi manca. Buona fortuna!

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top