如何使用 swig 管理 Ruby 垃圾收集器
How to manage the Ruby Garbage collector with swig
我有一个 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
问题是如果垃圾收集器删除解析器对象,所有对函数对象方法的调用都会导致段错误。那是因为我的 C++ Function 对象只使用指向由 Parser 对象分配的内存的指针。
我想找到一种方法告诉 GC 在使用 Function 对象时不要释放 HeaderParser 对象
我试过使用像
这样的指令
%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++ 接口的信息
我有一个 main class 初始化一个 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;
};
So Function class 方法构造如下:
std::string Function::getName() const
{
if(m_function)
return m_function->getNameInfo().getAsString();
else
return std::string();
}
我只是需要简化所有内容才能使它起作用。
在 HeaderParser class 中,而不是直接 return 一个 std::vector<Function>
with :
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
...
我有一个 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
问题是如果垃圾收集器删除解析器对象,所有对函数对象方法的调用都会导致段错误。那是因为我的 C++ Function 对象只使用指向由 Parser 对象分配的内存的指针。
我想找到一种方法告诉 GC 在使用 Function 对象时不要释放 HeaderParser 对象
我试过使用像
这样的指令%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++ 接口的信息 我有一个 main class 初始化一个 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;
};
So Function class 方法构造如下:
std::string Function::getName() const
{
if(m_function)
return m_function->getNameInfo().getAsString();
else
return std::string();
}
我只是需要简化所有内容才能使它起作用。
在 HeaderParser class 中,而不是直接 return 一个 std::vector<Function>
with :
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
...