我正在写一个宝石,其中一个难点是我的camelize
方法。我开始用C重写它,并且它正在使用以下实现:
#include <ctype.h>
#include <ruby.h>
VALUE MyGem = Qnil;
VALUE Utils = Qnil;
VALUE camelize(VALUE self, VALUE str)
{
char *orig_str = rb_string_value_cstr(&str);
char new_str[strlen(orig_str)];
char prev;
int orig_idx = 0, new_idx = 0;
new_str[0] = toupper(orig_str[0]);
for (orig_idx = 1, new_idx = 1; orig_str[orig_idx] != '\0'; orig_idx++) {
if (prev == '_') {
new_str[new_idx++] = toupper(orig_str[orig_idx]);
}
else if (orig_str[orig_idx] != '_') {
new_str[new_idx++] = orig_str[orig_idx];
}
prev = orig_str[orig_idx];
}
return rb_str_new(new_str, new_idx);
}
void Init_my_gem()
{
MyGem = rb_define_module("MyGem");
Utils = rb_define_module_under(MyGem, "Utils");
rb_define_singleton_method(Utils, "camelize", camelize, 1);
}
唯一的问题是,VALUE str
可以是符号或字符串。有人知道如何将str
值转换为字符串,然后再将其转换为char*
吗?
答案 0 :(得分:2)
最简单的方法是在to_s
上致电str
(rb_string_value_cstr
将尝试使用to_str
,而不是to_s
):
str = rb_funcall(str, rb_intern("to_s"), 0);
如果您希望这只适用于符号,则可以明确检查它们。在这种情况下,如果需要,可以直接调用为符号实现to_s
的函数(如果你这样做,即使你打开Symbol#to_s
类并更换它,也会始终使用原始的Symbol
它有不同的实现):
if (TYPE(str) == T_SYMBOL) {
str = rb_sym_to_s(str);
}
另一个选择是rb_convert_type
使用to_s
方法,这是(据我所知)几乎相当于只调用to_s
:
str = rb_convert_type(str, T_STRING, "String", "to_s");