如何使用swig管理Ruby垃圾回收器

How to manage the Ruby Garbage collector with swig

本文关键字:Ruby 何使用 swig 管理      更新时间:2023-10-16

我有一个C++接口,我用swig为它创建ruby绑定。我可以构建这些绑定,但垃圾回收器有问题。我的ruby代码如下:

parser = HeaderParser.new(source_file, ['/usr/lib'])
parser.parse
functions = parser.getFunctions //Array of Ruby wrapped class named  Function
functions.each do |f|
  puts f.getName
end

问题是,如果垃圾收集器删除了解析器对象,那么所有对Function对象方法的调用都会导致Segfault。这是因为我的C++函数对象只使用指向Parser对象分配的内存的指针。

我想找到一种方法来告诉GC不要释放HeaderParser对象,因为有使用的Function对象

我试过使用这样的指令

%trackbobjects 

并像文档中那样为垃圾收集器编写一个ruby标记函数,但没有成功

%header %{
  static void mark_HeaderParser(void* ptr) {
  TruckBoris::HeaderParser* hp = (TruckBoris::HeaderParser*) ptr;
  /* Loop over each object and tell the garbage collector
  that we are holding a reference to them. */
  std::vector<TruckBoris::Function> fns;
  fns = hp->getFunctions();
  int count = fns.size();
  for(int i = 0; i < count; ++i) {
    TruckBoris::Function fn = fns[i];
    VALUE object = SWIG_RubyInstanceFor(&fn);
    if (object != Qnil) {
      rb_gc_mark(object);
    }
  }
  }
%}

C++接口上的信息我有一个初始化Clang CompilerInstance和ASTConsumer:的主类

class HeaderParser
{
  public:
    HeaderParser();
    HeaderParser( std::string sourceFile, std::vector<std::string> headersPaths);
    ~HeaderParser();
    ...
    bool parse(bool mainFile = false);
    ...
    std::vector<Function> getFunctions() const;
    ...
private:
    ...
    clang::CompilerInstance m_ci;
    HeaderElements *m_headerElements; // an ASTConsumer
};

当调用HeaderParser::parse方法时,它解析源文件并填充Function对象的向量。

这些对象只是使用FunctionDecl指针指向由HeaderParser中的compilerInstance分配的内存。

class Function 
{
 public:
   Function();
   Function(clang::FunctionDecl * fn);
   ~Function() {}
   std::string getName() const; 
 private:
   clang::FunctionDecl * m_function;
};

因此函数类方法构造如下:

std::string Function::getName() const
{
  if(m_function)
    return m_function->getNameInfo().getAsString();
  else
    return std::string();
}

我只需要简化所有内容就可以了。

在HeaderParser类中,不直接返回带有:的std::vector<Function>

std::vector<Function> getFunctions() const;

我使用过:

int nbFunctions() const;
Function getFunction(int) const;

并且,删除mark指令,让swig执行magik。之后,我只需要在我的ruby lib文件中添加:

class Rtruckboris::HeaderParser
  def functions
    fns=[]
    (0..(functions_num() -1)).each do |i|
      fns<<get_nth_function(i)
    end
    fns
  end 
...