C RubyLine包含另一个生成的文件,以从该文件调用函数
我有两个Ruby的C扩展(用于Rails应用程序)。在初始化之后,我在C RubyLine包含另一个生成的文件,以从该文件调用函数,c,ruby,C,Ruby,我有两个Ruby的C扩展(用于Rails应用程序)。在初始化之后,我在application.rb中使用config 这是第一节课: class Object require 'inline' inline do |builder| builder.c <<-EOC static VALUE rb_obj_is_number(){ // code to return Qtrue or Qfalse }
application.rb
中使用config
这是第一节课:
class Object
require 'inline'
inline do |builder|
builder.c <<-EOC
static VALUE
rb_obj_is_number(){
// code to return Qtrue or Qfalse
}
EOC
end
alias is_number rb_obj_is_number
end
尝试将函数从一个文件调用到另一个文件时,出现以下错误:
dyld: lazy symbol binding failed: Symbol not found: _rb_obj_is_number
我想这是因为我没有在第二个文件中包含第一个生成的文件。
如何才能让编译器识别出rb\u obj\u is \u number
?您的函数在单独的编译单元中声明为static
,因此当然rb\u ari\u一些乐趣
无法看到rb\u is \u number
。我马上想到两个选择:
一个选项是将rb_obj_is_number
的C实现放在一个字符串中,该字符串可供builder.C
调用访问。这将为您提供两份函数副本,但:
- 这两种实现都是静态的,因此不会出现名称空间问题
- 实现可能足够小,因此额外的膨胀不会成为问题
- 这两个实现都来自同一个字符串,因此保持它们不变应该不会有问题
你会有这样的东西:
# In some library file...
module CUtil
IS_NUMBER = %q{
static VALUE rb_obj_is_number(void) { /*...*/ }
}
end
# When monkey patching Object...
class Object
require 'inline'
inline do |builder|
builder.c CUtil::IS_NUMBER
end
alias is_number rb_obj_is_number
end
# When monkey patching Array...
class Array
require 'inline'
inline do |builder|
builder.c <<-EOC
#{CUtil::IS_NUMBER}
static VALUE rb_ary_some_fun(void) { /*...*/ }
EOC
end
alias some_fun rb_ary_some_fun
end
/* There's no need to call this over and over again inside a loop. */
ID is_number = rb_intern("is_number");
/* ... */
if(rb_funcall(c_arr[i], is_number, 0) == Qtrue) {
result += NUM2DBL(c_arr[i]);
}
此外,我建议您使用适当的函数签名(即rb_obj_is_number(void)
),以确保编译器不会以K&R模式结束。您还应该调整编译器的警告标志,以便它大声抱怨这类事情。您的函数在单独的编译单元中声明为静态
,因此当然rb\u ari\u一些乐趣
无法看到rb\u obj\u is\u number
。我马上想到两个选择:
一个选项是将rb_obj_is_number
的C实现放在一个字符串中,该字符串可供builder.C
调用访问。这将为您提供两份函数副本,但:
- 这两种实现都是静态的,因此不会出现名称空间问题
- 实现可能足够小,因此额外的膨胀不会成为问题
- 这两个实现都来自同一个字符串,因此保持它们不变应该不会有问题
# In some library file...
module CUtil
IS_NUMBER = %q{
static VALUE rb_obj_is_number(void) { /*...*/ }
}
end
# When monkey patching Object...
class Object
require 'inline'
inline do |builder|
builder.c CUtil::IS_NUMBER
end
alias is_number rb_obj_is_number
end
# When monkey patching Array...
class Array
require 'inline'
inline do |builder|
builder.c <<-EOC
#{CUtil::IS_NUMBER}
static VALUE rb_ary_some_fun(void) { /*...*/ }
EOC
end
alias some_fun rb_ary_some_fun
end
/* There's no need to call this over and over again inside a loop. */
ID is_number = rb_intern("is_number");
/* ... */
if(rb_funcall(c_arr[i], is_number, 0) == Qtrue) {
result += NUM2DBL(c_arr[i]);
}
此外,我建议您使用适当的函数签名(即rb_obj_is_number(void)),以确保编译器不会以K&R模式结束。您还应该调整编译器的警告标志,以便它大声抱怨这类事情。解决方案#2正是我想要的。解决方案1也是教育性的。感谢您花时间发布如此详细的回复。解决方案2正是我想要的。解决方案1也是教育性的。感谢您花时间发布如此详细的回复。