2

SWIG を使用して、Ruby スクリプトを C++ ライブラリにラップします。Ruby では、C++ クラスから継承できますが、結果のポインターを C++ 関数にポリモーフィックに渡すことはできません。

これが具体的な例です。SWIG インターフェイス ファイルは、仮想関数 sound() を持つ基本クラス Animal を定義します。

[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 オブジェクトをアニマルへのポインターとして扱うことができません。何か案は?

4

2 に答える 2

4

swig-userメーリングリストでTobias Grimmから問題の解決策を得ました。問題の最初の部分は、SWIG の誤解を招くエラー メッセージです。このメッセージは、C++ 関数に間違った型のポインターを渡していることを示唆しているようですが、そうではありません。Ruby で例外のクラスを確認すると、それは ObjectPreviouslyDeleted です。これは、私の Cat クラスの基になる C 構造体ポインターが NULL であることを意味します。したがって、実際の問題は、ポインターの型が間違っていることではなく、ポインターが NULL であることです。

Cat の initialize() メソッドで "super" を呼び出すのを単に忘れたため、ポインターは NULL です。このように、Cat の作成では、Animal コンストラクターが呼び出されないため、基礎となる C 構造体が割り当てられません。'super' の呼び出しを忘れることは、Ruby の初心者がよく犯す間違いです。特に、自動コンストラクター チェーンに慣れている C++ 出身の私のような人にとってはなおさらです。

だから私がしなければならなかったのは、「スーパー」への呼び出しを追加することだけでした:

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

これで問題なく動作します。ありがとう、トバイアス。

于 2009-02-26T15:41:09.650 に答える
1

インスタンスへのポインターを返すヘルパー関数を定義する必要があると思います。私は fopen でポインターしか使用していないので、これが本当に機能するかどうか、または他に不足しているものがあるかどうかはわかりません。幸運を!

于 2009-02-17T20:03:12.870 に答える