简体   繁体   English

如何使用Swig管理Ruby垃圾收集器

[英]How to manage the Ruby Garbage collector with swig

I have a C++ interface for which I create ruby bindings with swig. 我有一个C ++接口,可使用swig创建红宝石绑定。 I am able to build those bindings but I have a problem with the Garbage Collector. 我能够构建这些绑定,但是垃圾收集器存在问题。 My ruby code looks like this: 我的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

The problem is that if the garbage collector delete the parser object, all call to Function objects methods result in a Segfault. 问题在于,如果垃圾回收器删除了解析器对象,则对Function对象方法的所有调用都会导致Segfault。 That because my C++ Function object just use pointer to memory allocated by the Parser object. 那是因为我的C ++ Function对象只使用了指向Parser对象分配的内存的指针。

I would like to find a way to tell the GC to not free the HeaderParser object while there are Function object used 我想找到一种方法来告诉GC在使用Function对象时不要释放HeaderParser对象

I have tried to use directive like 我尝试使用像

%trackbobjects 

and write a ruby mark function for the garbage collector like in the documentation but without success 并像文档中那样为垃圾收集器编写一个ruby mark函数,但是没有成功

%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);
    }
  }
  }
%}

Informations on the C++ interface I have a main class that initialize a Clang CompilerInstance and an ASTConsumer: 关于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
};

When the HeaderParser::parse method is called, it parses a source file and fill a vector of Function objects. 调用HeaderParser :: parse方法时,它将解析源文件并填充Function对象的向量。

Those objects just use FunctionDecl pointers to memory allocated by the compilerInstance in The HeaderParser. 这些对象仅使用FunctionDecl指针指向HeaderParser中的editor分配的内存。

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

So Function class methods are constructed like this: 因此,Function类方法的构造如下:

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

I just needed to simplify all in order tomake this works. 我只需要简化所有内容即可使其正常工作。

In the HeaderParser class, instead of directly return a std::vector<Function> with : 在HeaderParser类中,不是直接使用以下命令返回std::vector<Function>

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

I have used : 我用过 :

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

and, remove the mark directives, and let swig do the magick. 然后,删除mark指令,然后让wig来做魔术。 After that I just have to add in my ruby lib file : 之后,我只需要添加我的ruby lib文件:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM