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

Posted

技术标签:

【中文标题】使用 SWIG 跨 C++ 和 Ruby 的多态性【英文标题】:Polymorphism across C++ and Ruby using SWIG 【发布时间】:2009-02-14 15:36:40 【问题描述】:

我使用 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 对象视为指向动物的指针。有什么想法吗?

【问题讨论】:

【参考方案1】:

我从 swig-user 邮件列表中的 Tobias Grimm 那里得到了我的问题的解决方案。 问题的第一部分是 SWIG 的误导性错误消息。 该消息似乎表明我将错误类型的指针传递给我的 C++ 功能,但事实并非如此。如果您检查异常的类 在 Ruby 中,它是 ObjectPreviousDeleted,这意味着底层的 C 结构指针 我的 Cat 课程为 NULL。所以真正的问题是指针是NULL, 并不是它的类型不对。

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

所以我所要做的就是添加对“super”的调用:

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

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

【讨论】:

谢谢你!真的,如果 super() 没有从覆盖的 initialize() 方法中调用,那么在将 Ruby 传递给 C++ 时会出现错误 ObjectPreviouslyDeleted【参考方案2】:

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

【讨论】:

以上是关于使用 SWIG 跨 C++ 和 Ruby 的多态性的主要内容,如果未能解决你的问题,请参考以下文章

SWIG C++ Python 多态性和多线程

Typedef、Ruby 和 SWIG

swig python wrap c++​​ 指向多态类型的指针向量

将 SWIG 与 C++ 模板函数一起使用

Ruby 和 SWIG 与 CMake

swig 对基类“std::string”一无所知,被忽略