我使用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的指针。有什么想法吗?
答案 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的指针,所以我不知道这是否真的有用,或者是否还有其他我缺少的东西。 祝你好运!