2015-02-05 3 views
0

У меня есть интерфейс C++, для которого я создаю рубиновые привязки с помощью swig. Я могу построить эти привязки, но у меня проблема с сборщиком мусора. Мой рубиновый код выглядит следующим образом:Как управлять сборщиком мусора Ruby с swig

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 

Проблема заключается в том, что если сборщик мусора удалить объект парсера, все вызов функции объектов методы приводят к Segfault. Это потому, что мой объект C++ Function просто использует указатель на память, выделенную объектом Parser.

Я хотел бы найти способ, чтобы сказать GC не освобождает объект HeaderParser пока есть объект Function используется

Я пытался использовать директиву как

%trackbobjects 

и написать знак рубин функция для сборки мусора, как в документации, но без успеха

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

информации на с ++ интерфейс У меня есть основной класс, который инициализирует лязгом 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 :: синтаксического анализа вызывается метод, он анализирует исходный файл и заполнить вектор функциональных объектов.

Эти объекты просто используют указатели FunctionDecl в памяти, выделенные компиляторомInstance в HeaderParser.

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

Так как методы класса Function построены следующим образом:

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

ответ

0

мне просто нужно, чтобы упростить все в порядке tomake это работает.

В классе HeaderParser, вместо того, чтобы непосредственно возвращать std::vector<Function> с:

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

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

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

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

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