【发布时间】:2015-06-25 13:30:45
【问题描述】:
我有一个 Rails 应用程序需要显示 Monte Carlo sim 的结果,而且第一次,Ruby 的速度不足以满足我的需求。因此,我开始四处寻找是否可以用 C 重写我的模拟并在 Ruby 中使用这些结果,并且一些谷歌搜索发现了 RubyInline gem,以便轻松地直接在 Ruby 中编写更快的 C 代码。做一些简单的事情效果很好,例如,一些用 Ruby 和 C 编写的基本函数:
class FasterFunctions
inline do |builder|
builder.c '
double rand_sum(int trials)
{
double sum = 0.0;
for (int i = 0; i<trials; i++)
{
sum += (double)rand()/(double)RAND_MAX;
}
return sum;
}'
builder.c '
long loop_sum(long trials)
{
long sum = 0;
for (long i = 0; i<trials; i++)
{
sum+=i;
}
return sum;
}'
end
end
#the C version is 4 orders of magnitude faster
trials = 1_000_000
ruby_sum = 0
trials.times {|i| ruby_sum += i}
c_sum = FasterRand.new.loop_sum(trials)
# the C version is 1 order of magnitude faster
ruby_sum = 0.0
trials.times {ruby_sum += rand}
c_sum = FasterRand.new.rand_sum(trials)
所以,太好了,它肯定会加快我的模拟速度,因为它几乎只是生成随机数并根据这些结果添加东西。不幸的是,除了像这样的基本内容之外,我无法弄清楚如何实际编写我的程序。我需要传递一些结构来充当状态变量,因此首要任务是弄清楚如何创建 C 结构。看了the documentation,感觉应该挺简单的。
访问器(方法、类型、成员 = 方法)
为通过包装的 C 结构成员添加读取器和写入器 Data_Wrap_Struct。方法是赋予访问者的红宝石名称,类型 是C型。除非 C 成员名称被 member 覆盖,否则 方法名用作结构成员。
builder.struct_name = 'MyStruct' builder.accessor :title, 'char *' builder.accessor :stream_index, 'int', :index
文档对我来说并不完全清楚,但我认为我会像以前一样将它放在一个类中并执行以下操作来访问它:
class MyStructClass
inline do |builder|
builder.struct_name = 'MyStruct'
builder.accessor :title, 'char *'
builder.accessor :stream_index, 'int', :index
end
end
#possible this
struct = MyStructClass.new.MyStruct
struct.title = 'A Title'
#or maybe
struct = MyStructClass.new
struct.title = 'A Title'
不幸的是,我什至无法做到这一点
*/.rbenv/versions/2.1.2/lib/ruby/gems/2.1.0/gems/RubyInline-3.12.4/lib/inline.rb:456:3: 错误:使用未声明的标识符 'MyStruct' 我的结构 * 指针; ^ */.rbenv/versions/2.1.2/lib/ruby/gems/2.1.0/gems/RubyInline-3.12.4/lib/inline.rb:456:13:错误:使用未声明的标识符 '指针' MyStruct *指针; ^ */.rbenv/versions/2.1.2/lib/ruby/gems/2.1.0/gems/RubyInline-3.12.4/lib/inline.rb:458:35:错误:使用未声明的标识符 '指针' Data_Get_Struct(self, MyStruct, 指针); ^ /.rbenv/versions/2.1.2/include/ruby-2.1.0/ruby/ruby.h:1038:6:注意:从宏“Data_Get_Struct”扩展 (sval) = (type)DATA_PTR(obj);\ ^ */.rbenv/versions/2.1.2/lib/ruby/gems/2.1.0/gems/RubyInline-3.12.4/lib/inline.rb:458:25:错误:使用未声明的标识符 'MyStruct' Data_Get_Struct(self, MyStruct, 指针); ^ /.rbenv/versions/2.1.2/include/ruby-2.1.0/ruby/ruby.h:1038:15:注意:从宏“Data_Get_Struct”扩展 (sval) = (type)DATA_PTR(obj);\ ^ */.rbenv/versions/2.1.2/lib/ruby/gems/2.1.0/gems/RubyInline-3.12.4/lib/inline.rb:458:3: 错误:预期表达式 Data_Get_Struct(self, MyStruct, pointer); ^ /.rbenv/versions/2.1.2/include/ruby-2.1.0/ruby/ruby.h:1038:20:注意:从宏“Data_Get_Struct”扩展 (sval) = (type)DATA_PTR(obj);\ ^ */.rbenv/versions/2.1.2/lib/ruby/gems/2.1.0/gems/RubyInline-3.12.4/lib/inline.rb:460:23:错误:使用未声明的标识符 “指针”返回(rb_str_new2(指针->标题)); ^ */.rbenv/versions/2.1.2/include/ruby-2.1.0/ruby/intern.h:786:27:注意:从宏“rb_str_new_cstr”扩展 (__builtin_constant_p(str)) ? \ ^ */.rbenv/versions/2.1.2/lib/ruby/gems/2.1.0/gems/RubyInline-3.12.4/lib/inline.rb:460:23:错误:使用未声明的标识符 '指针' */.rbenv/versions/2.1.2/include/ruby-2.1.0/ruby/intern.h:787:14:注意:从宏“rb_str_new_cstr”扩展 rb_str_new((str), (long)strlen(str)) : \ ^ */.rbenv/versions/2.1.2/lib/ruby/gems/2.1.0/gems/RubyInline-3.12.4/lib/inline.rb:460:23:错误:使用未声明的标识符 '指针' */.rbenv/versions/2.1.2/include/ruby-2.1.0/ruby/intern.h:787:33:注意:从宏“rb_str_new_cstr”扩展 rb_str_new((str), (long)strlen(str)) : \ ^ */.rbenv/versions/2.1.2/lib/ruby/gems/2.1.0/gems/RubyInline-3.12.4/lib/inline.rb:460:23:错误:使用未声明的标识符 '指针' */.rbenv/versions/2.1.2/include/ruby-2.1.0/ruby/intern.h:788:18:注意:从宏“rb_str_new_cstr”扩展 rb_str_new_cstr(str); \ ^ */.rbenv/versions/2.1.2/lib/ruby/gems/2.1.0/gems/RubyInline-3.12.4/lib/inline.rb:460:10:错误:从 具有不兼容结果类型'VALUE'(又名'unsigned long')的函数返回(rb_str_new2(pointer->title)); ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */.rbenv/versions/2.1.2/lib/ruby/gems/2.1.0/gems/RubyInline-3.12.4/lib/inline.rb:478:3: 错误:使用未声明的标识符 'MyStruct' 我的结构 * 指针; ^ */.rbenv/versions/2.1.2/lib/ruby/gems/2.1.0/gems/RubyInline-3.12.4/lib/inline.rb:478:13:错误:使用未声明的标识符 '指针' MyStruct *指针; ^ */.rbenv/versions/2.1.2/lib/ruby/gems/2.1.0/gems/RubyInline-3.12.4/lib/inline.rb:480:35:错误:使用未声明的标识符 '指针' Data_Get_Struct(self, MyStruct, 指针); ^ /.rbenv/versions/2.1.2/include/ruby-2.1.0/ruby/ruby.h:1038:6:注意:从宏“Data_Get_Struct”扩展 (sval) = (type)DATA_PTR(obj);\ ^ */.rbenv/versions/2.1.2/lib/ruby/gems/2.1.0/gems/RubyInline-3.12.4/lib/inline.rb:480:25:错误:使用未声明的标识符 'MyStruct' Data_Get_Struct(self, MyStruct, 指针); ^ /.rbenv/versions/2.1.2/include/ruby-2.1.0/ruby/ruby.h:1038:15:注意:从宏“Data_Get_Struct”扩展 (sval) = (type)DATA_PTR(obj);\ ^ */.rbenv/versions/2.1.2/lib/ruby/gems/2.1.0/gems/RubyInline-3.12.4/lib/inline.rb:480:3: 错误:预期表达式 Data_Get_Struct(self, MyStruct, pointer); ^ /.rbenv/versions/2.1.2/include/ruby-2.1.0/ruby/ruby.h:1038:20:注意:从宏“Data_Get_Struct”扩展 (sval) = (type)DATA_PTR(obj);\ ^ */.rbenv/versions/2.1.2/lib/ruby/gems/2.1.0/gems/RubyInline-3.12.4/lib/inline.rb:482:3: 错误:使用未声明的标识符 'pointer' 指针->title = StringValuePtr(value); ^ */.rbenv/versions/2.1.2/lib/ruby/gems/2.1.0/gems/RubyInline-3.12.4/lib/inline.rb:456:3: 错误:使用未声明的标识符 'MyStruct' 我的结构 * 指针; ^ */.rbenv/versions/2.1.2/lib/ruby/gems/2.1.0/gems/RubyInline-3.12.4/lib/inline.rb:456:13:错误:使用未声明的标识符 '指针' MyStruct *指针; ^ */.rbenv/versions/2.1.2/lib/ruby/gems/2.1.0/gems/RubyInline-3.12.4/lib/inline.rb:458:35:错误:使用未声明的标识符 '指针' Data_Get_Struct(self, MyStruct, 指针); ^ /.rbenv/versions/2.1.2/include/ruby-2.1.0/ruby/ruby.h:1038:6:注意:从宏“Data_Get_Struct”扩展 (sval) = (type)DATA_PTR(obj);\ ^ 致命错误:发出的错误太多,现在停止 [-ferror-limit=]
我已经进行了大量的谷歌搜索,但我发现的几乎每个示例都只涉及我最初概述的简单用例。它吐出的第一个错误是 MyStruct 未声明,所以我尝试在访问器方法之前添加一个结构定义,如下所示:
builder.c '
typedef struct
{
char *title;
int index;
} MyStruct;
'
这没有任何作用,并且文档似乎很清楚 c 方法仅用于声明函数,而不是结构。我不确定接下来要尝试什么,有其他人有这方面的经验吗?
【问题讨论】: