使用SWIG跨C ++和Ruby的多态性

时间:2009-02-14 15:36:40

标签: c++ ruby inheritance polymorphism swig

我使用SWIG围绕C ++库包装Ruby脚本。在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对象视为指向Animal的指针。有什么想法吗?

2 个答案:

答案 0 :(得分:4)

我在swig-user邮件列表中找到了Tobias Grimm的问题解决方案。 问题的第一部分是SWIG的误导性错误消息。 该消息似乎暗示我将错误类型的指针传递给我的C ++ 功能,但事实并非如此。如果检查异常的类 在Ruby中,它的ObjectPreviouslyDeleted,意味着底层的C struct指针 我的Cat类是NULL。所以真正的问题是指针是NULL, 并不是说它有错误的类型。

指针为NULL因为我忘了在Cat的initialize()中调用“super” 方法。这样,随着Cat的创建没有分配底层C结构, 因为Animal构造函数永远不会被调用。 忘记调用'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

现在工作正常。谢谢,托比亚斯。

答案 1 :(得分:1)

我认为您需要定义一个helper function,它返回指向您实例的指针。 我只使用了fopen的指针,所以我不知道这是否真的有用,或者是否还有其他我缺少的东西。 祝你好运!