[英]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.