使用SWIG在C ++和Ruby上的多态性 [英] Polymorphism across C++ and Ruby using SWIG

查看:85
本文介绍了使用SWIG在C ++和Ruby上的多态性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用SWIG将Ruby脚本包装在C ++库周围。在Ruby中,我可以继承一个C ++类,但是我不能以多态方式将结果指针传递给C ++函数。

I use SWIG to wrap a Ruby script around a C++ library. In Ruby, I can inherit from a C++ class, but I cannot pass the resulting pointer to a C++ function in a polymorphic way.

这是一个具体的例子。 SWIG界面文件用虚函数sound()定义基类Animal:

Here is a concrete example. The SWIG interface file defines base class Animal with virtual function 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脚本如下所示:

Note that I use SWIG directors for cross-language polymorphism, but this does not seem to work. The Ruby script looks like this:

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

脚本中的最后一行会产生此错误:

The final line in the script produces this error:

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

所以不知何故SWIG不允许我把Ruby对象当作指向动物的指针。任何想法?

So somehow SWIG does not allow me to treat the Ruby object as a pointer-to-Animal. Any ideas?

推荐答案

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

I got a solution to my problem from Tobias Grimm at the swig-user mailing list. The first part of the problem is SWIG's misleading error message. The message seems to suggest that I pass the wrong type of pointer to my C++ function, but this is not the case. If you check the class of the exception in Ruby, it's ObjectPreviouslyDeleted, meaning that the underlying C struct pointer of my Cat class is NULL. So the real problem is that the pointer is NULL, not that it has the wrong type.

指针是NULL,因为我只是忘了调用super 在Cat的initialize()
方法中。这样,由于Cat的创建没有底层的C结构体被分配,
因为Animal的构造函数永远不会被调用。
忘记调用'super'是一个非常常见的Ruby初学者的错误,特别是对于像我这样来自C ++,习惯于自动构造函数链接的人来说,

The pointer is NULL because I simply forgot to call "super" in Cat's initialize() method. This way, with the creation of Cat no underlying C struct gets allocated, because the Animal constructor never gets called. Forgetting to call 'super' is a very common Ruby-beginner's mistake, especially for people like me who come from C++, who are used to automatic constructor chaining.

所以我只需要添加一个调用'super':

So all I had to do was add a call to 'super':

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

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

This now works fine. Thanks, Tobias.

这篇关于使用SWIG在C ++和Ruby上的多态性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆