Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/55.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ruby/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C RubyLine包含另一个生成的文件,以从该文件调用函数_C_Ruby - Fatal编程技术网

C RubyLine包含另一个生成的文件,以从该文件调用函数

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 }

我有两个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
      }
    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也是教育性的。感谢您花时间发布如此详细的回复。