我最近更新到Mountain Lion并重新安装了Ruby,但是当我尝试运行测试Rails应用程序时,我收到一条错误消息,指出我的系统上"当前未安装Rails".我按照它说的做,输入sudo gem install rails并获得:
cleared faster_require caches due to new gem install...
Successfully installed rails-3.2.7
1 gem installed
Installing ri documentation for rails-3.2.7...
Installing RDoc documentation for rails-3.2.7...
Run Code Online (Sandbox Code Playgroud)
但是当我检查安装哪个rails版本时,我得到的是:
Rails is not currently installed on this system. To get the latest version, simply type:
$ sudo gem install rails
You can then rerun your "rails" command.
Run Code Online (Sandbox Code Playgroud)
我也尝试过gem install rails:
Building native extensions. This could take a while...
ERROR: Error installing rails:
ERROR: Failed to build …Run Code Online (Sandbox Code Playgroud) 所以,最近我不幸地需要为Ruby做一个C扩展(因为性能).由于我是有了解的问题VALUE(和仍然),所以我看着Ruby源代码,并发现:typedef unsigned long VALUE;(链接到源代码,但你会发现,有它做了一些其他的"方式",但我认为它本质上是一个long; 如我错了请纠正我).因此,在进一步调查时,我发现了一篇有趣的博文,其中说:
"......在某些情况下,VALUE对象可能是数据,而不是指向数据."
是什么让我困惑的是,当我试图将一个字符串在Ruby传递到C,并使用RSTRING_PTR();上VALUE(通过在Ruby的C函数),并尝试"调试"它与strlen();它返回4. 总是 4.
示例代码:
VALUE test(VALUE inp) {
unsigned char* c = RSTRING_PTR(inp);
//return rb_str_new2(c); //this returns some random gibberish
return INT2FIX(strlen(c));
}
Run Code Online (Sandbox Code Playgroud)
此示例始终返回1作为字符串长度:
VALUE test(VALUE inp) {
unsigned char* c = (unsigned char*) inp;
//return rb_str_new2(c); // Always "\x03" in Ruby.
return INT2FIX(strlen(c));
}
Run Code Online (Sandbox Code Playgroud)
有时在ruby中我看到一个异常,说"无法将模块转换为字符串"(或者沿着这些行, 但是我正在弄乱代码,试图解决这个问题,我现在无法重现错误当我尝试时会发生错误StringValuePtr();[我有点不清楚这究竟是做什么的.文档说它将传递的参数更改为char*inp):
VALUE test(VALUE inp) {
StringValuePtr(inp);
return …Run Code Online (Sandbox Code Playgroud) 我正在尝试为ruby写一个C扩展,它将生成一个类.我正在研究如何为类定义一些默认参数.例如,如果我在ruby中有这个类的decleration:
class MyClass
def initialize(name, age=10)
@name = name
@age = age
end
end
Run Code Online (Sandbox Code Playgroud)
您可以使用它进行初始化mc = MyClass.new("blah"),并在内部设置age参数.我怎么用C做这个?到目前为止,我得到了这个,但这迫使进入另一个论点:
require "ruby.h"
static VALUE my_init(VALUE self, VALUE name, VALUE age)
{
rb_iv_set(self, "@name", name);
rb_iv_set(self, "@age", age);
return self;
}
VALUE cMyClass;
void Init_MyClass()
{
// create a ruby class instance
cMyClass = rb_define_class("MyClass", rb_cObject);
// connect the instance methods to the object
rb_define_method(cMyClass, "initialize", my_init, 2);
}
Run Code Online (Sandbox Code Playgroud)
我考虑过检查age反对Qnil或使用的价值if ( TYPE(age) == T_UNDEF ),但我只是从那里得到段错误.阅读README.EXT …
我正在开发一个gem,它目前是纯Ruby,但我也一直在为其中一个功能开发一个更快的C变种.该功能在纯Ruby中可用,但有时很慢.缓慢只会影响一些潜在用户(取决于他们需要哪些功能,以及他们如何使用它们),因此如果无法在目标系统上编译,那么将gem提供给具有Ruby功能的优雅回退是有意义的.
我想在一个gem中维护该功能的Ruby和C变体,并在安装时提供gem的最佳(即最快)体验.这将使我能够从我的一个项目中支持最广泛的潜在用户.它还允许其他人的依赖宝石和项目使用目标系统上最好的可用依赖性,而不是兼容性最低的通用分母版本.
我希望require在运行时回退出现在主lib/foo.rb文件中,就像这样:
begin
require 'foo/foo_extended'
rescue LoadError
require 'foo/ext_bits_as_pure_ruby'
end
Run Code Online (Sandbox Code Playgroud)
但是,我不知道如何让gem安装检查(或尝试和失败)本机扩展支持,以便gem安装正确,无论它是否可以构建'foo_extended'.当我研究如何做到这一点时,我主要发现了几年前的讨论,例如http://permalink.gmane.org/gmane.comp.lang.ruby.gems.devel/1479和http://rubyforge.org/ pipermail/rubygems-developers/2007-November/003220.html暗示Ruby宝石并不真正支持这一功能.最近没有什么,所以我希望SO上的某些人有更多最新的知识?
我的理想解决方案是在尝试构建扩展之前检测目标Ruby不支持(或者可能根本不希望在项目级别)C本机扩展的方法.但是,如果不是太脏,尝试/捕获机制也可以.
这有可能,如果是这样的话怎么样?或者建议发布两个宝石变体(例如foo和foo_ruby),我在搜索时发现,仍然是目前的最佳实践?
我正在编写Ruby扩展并使用该函数Data_wrap_struct.
为了参与Ruby的标记和清除垃圾收集过程,我需要定义一个例程来释放我的结构,以及一个例程来标记从我的结构到其他结构的任何引用.我通过经典free函数释放内存,但我不知道如何使用标记功能.
我的结构听起来像这样
typedef struct
{
int x;
int y;
} A;
typedef struct
{
A collection[10];
int current;
} B;
Run Code Online (Sandbox Code Playgroud)
我认为我需要一个标记函数来标记collection结构B中的引用.
有人可以给我看一个例子来看看标记功能是如何工作的吗?
如何从C扩展中处理Ruby 2.0.0关键字参数?
背景
def example(name: 'Bob' hat_color: 'red')
puts "#{name} has a #{hat_color} hat!"
end
example #=> "Bob has a red hat!"
example(name: 'Joe', hat_color: 'blue') #=> "Joe has a blue hat!"
Run Code Online (Sandbox Code Playgroud)
在处理具有许多不同调用序列或选项的方法时,关键字参数(如上所述)非常有用.我在C扩展中有一个这样的方法(一个blit处理我项目中大部分OpenGL绘图的方法),我想知道如何从ruby中获取方法句柄关键字参数.
思路
根据我所做的一些研究,我认为这样的处理可以通过C函数的:选项来完成rb_scan_args.但是,我一直无法找到有关如何使用它的任何信息.
在红宝石中,
begin
# ...
rescue
# ...
end
Run Code Online (Sandbox Code Playgroud)
不会捕获不是子类的异常StandardError.在C中,
rb_rescue(x, Qnil, y, Qnil);
VALUE x(void) { /* ... */ return Qnil; }
VALUE y(void) { /* ... */ return Qnil; }
Run Code Online (Sandbox Code Playgroud)
会做同样的事情.我如何rescue Exception => e从ruby C扩展(而不仅仅是rescue => e)?
我想从我自己的C代码中调用ruby代码.如果引发异常,我必须rb_protect我调用的ruby代码.rb_protect看起来像这样:
VALUE rb_protect(VALUE (* proc) (VALUE), VALUE data, int * state)
Run Code Online (Sandbox Code Playgroud)
所以proc必须是一个接受VALUE参数和返回的函数VALUE.我必须调用许多不能以这种方式工作的函数.他怎么能rb_protect提出例外呢?
我曾想过Data_Make_Struct用来将所有东西都包装成一个ruby对象并在其上调用方法.Data_Make_Struct本身可以提出例外.我怎么样rb_protect Data_Make_Struct?
我在创建ruby扩展以导出我在OSX下写入ruby的C++库时遇到问题.这个简单的例子:
#include <boost/regex.hpp>
extern "C" void Init_bayeux()
{
boost::regex expression("^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\\?([^#]*))?(#(.*))?");
}
Run Code Online (Sandbox Code Playgroud)
导致抛出bad_cast异常:
#0 0x00000001014663bd in __cxa_throw ()
#1 0x00000001014cf6b2 in __cxa_bad_cast ()
#2 0x00000001014986f9 in std::use_facet<std::collate<char> > ()
#3 0x0000000101135a4f in boost::re_detail::cpp_regex_traits_base<char>::imbue (this=0x7fff5fbfe4d0, l=@0x7fff5fbfe520) at cpp_regex_traits.hpp:218
#4 0x0000000101138d42 in cpp_regex_traits_base (this=0x7fff5fbfe4d0, l=@0x7fff5fbfe520) at cpp_regex_traits.hpp:173
#5 0x000000010113eda6 in boost::re_detail::create_cpp_regex_traits<char> (l=@0x7fff5fbfe520) at cpp_regex_traits.hpp:859
#6 0x0000000101149bee in cpp_regex_traits (this=0x101600200) at cpp_regex_traits.hpp:880
#7 0x0000000101142758 in regex_traits (this=0x101600200) at regex_traits.hpp:75
#8 0x000000010113d68c in regex_traits_wrapper (this=0x101600200) at regex_traits.hpp:169
#9 0x000000010113bae1 in regex_data (this=0x101600060) at basic_regex.hpp:166
#10 …Run Code Online (Sandbox Code Playgroud) 我遇到了这段代码.
typedef __mpz_struct MP_INT;
typedef __mpz_struct mpz_t[1];
Run Code Online (Sandbox Code Playgroud)
这里的struct __mpz_struct是一个结构,它被定义为单个元素的数组.我理解这是一个通过C中的引用传递的技巧.然后mpz_t被用作声明变量的类型并将它们作为参数传递.此外,还有一个评论
/*
MP_INT*, MP_RAT* and MP_FLOAT* are used because they don't have side-effects
of single-element arrays mp*_t
*/
Run Code Online (Sandbox Code Playgroud)
他们在谈论什么样的副作用?