簡體   English   中英

使用SWIG在C ++和Ruby上實現多態

[英]Polymorphism across C++ and Ruby using SWIG

我使用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 Director用於跨語言多態性,但這似乎不起作用。 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對象視為指向動物的指針。 有任何想法嗎?

我從Tobias Grimm的使用者郵件列表中找到了解決問題的方法。 問題的第一部分是SWIG的誤導性錯誤消息。 該消息似乎表明我將錯誤類型的指針傳遞給了C ++函數,但事實並非如此。 如果在Ruby中檢查異常的類,則為ObjectPreviouslyDeleted,這意味着我的Cat類的基礎C結構指針為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

現在可以正常工作了。 謝謝托比亞斯。

我相信您需要定義一個輔助函數 ,該函數返回一個指向您實例的指針。 我僅將指針與fopen一起使用,所以我不知道這是否真的有效,或者是否缺少其他內容。 祝好運!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM