Как работать с Ruby Garbage collector с помощью swig

0

У меня есть интерфейс C++, для которого я создаю рубиновые привязки с swig. Я могу построить эти привязки, но у меня проблема с сборщиком мусора. Мой код 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 в памяти, выделенные компиляторомInstance в The HeaderParser.

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();
}
Теги:
swig

1 ответ

0
Лучший ответ

Мне просто нужно было упростить все, чтобы это работало.

В классе HeaderParser вместо прямого возврата std::vector<Function> с помощью:

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

Я использовал:

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

и, удалите директивы марки, и пусть swig сделает магию. После этого мне просто нужно добавить в свой файл ruby lib:

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

Ещё вопросы

Сообщество Overcoder
Наверх
Меню