简体   繁体   English

将 C 字符转换为 Ruby 字符串

[英]Convert C character into Ruby string

I am writing a sample C Ruby extension which needs a C character to Ruby string conversion.我正在编写一个示例 C Ruby 扩展,它需要 C 字符到 Z9916D1FC59FE252BC76446A2FE1Z61

I have created extconf.rb and a file called x.c.我创建了 extconf.rb 和一个名为 x.c 的文件。

extconf.rb: extconf.rb:

require 'mkmf'
create_makefile 'x'

x.c: x.c:

#include "ruby.h"

void Init_x() {
    char c = 'b' ;

    VALUE b = rb_str_new_cstr(c) ;
    rb_gv_set("$a", b) ;
    rb_global_variable(&b) ;
}

rb_str_new_cstr() expects a C string, not a character. rb_str_new_cstr() 需要一个 C 字符串,而不是一个字符。 When I compile and run this code, I get segmentation fault, and Ruby crashes.当我编译并运行此代码时,出现分段错误,并且 Ruby 崩溃。

I can do this instead, which works just fine:我可以这样做,效果很好:

#include "ruby.h"

void Init_x() {
    char *c = "b" ;

    VALUE b = rb_str_new_cstr(c) ;
    rb_gv_set("$a", b) ;
    rb_global_variable(&b) ;
}

But the problem is if I have something like fscanf(file, "%c", &char) which sets char to a character, I have to convert it to a string first and change %c to %1s , which sounds like a bit slower approach.但问题是,如果我有类似fscanf(file, "%c", &char)的东西将char设置为字符,我必须先将其转换为字符串并将%c更改为%1s ,这听起来有点慢方法。

Is there a way to directly convert a C character into a Ruby string?有没有办法直接将 C 字符转换为 Ruby 字符串?

The rb_str_new_cstr() function is only for null-terminated strings - so called C strings (thus the suffix). rb_str_new_cstr() function 仅适用于以空字符结尾的字符串 - 所谓的 C 字符串(因此是后缀)。 Besides various other variations the unsuffixed rb_str_new() function exists for use cases like yours in which you have characters and you know how many:除了各种其他变体之外,无后缀rb_str_new() function 存在于像您这样的用例中,其中您有字符并且您知道有多少:

#include "ruby.h"

void Init_x() {
    char c = 'b' ;

    VALUE b = rb_str_new(&c, 1); // or sizeof(c)
    rb_gv_set("$a", b) ;
}

Btw.顺便提一句。 you don't need to call rb_global_variable() here.你不需要在这里调用rb_global_variable() It has nothing to do with Ruby global variables.它与 Ruby 全局变量无关。 It is used to manually tell the garbage collector about Ruby objects not exposed to Ruby.它用于手动告诉垃圾收集器 Ruby 对象未暴露给 Ruby。 The garbage collector obviously knows about the created object since the string is accessible via $a in Ruby code.垃圾收集器显然知道创建的 object 因为字符串可以通过 Ruby 代码中$a访问。

I wouldn't worry much about the performance of reading 1 character, but char *c = "b";我不会太担心读取 1 个字符的性能,但是char *c = "b"; is a string literal and it is not mutable.是一个字符串文字,它是不可变的。
There are many detailed answers if you follow the duplicates.如果您遵循重复项,则有许多详细的答案

However, to read 1 byte you don't need fscanf() , because fgetc() does exactly that.但是,要读取 1 个字节,您不需要fscanf() ,因为fgetc()正是这样做的。

char c[2] = "b";    // 1 character + NULL

c[0] = fgetc(file); // returns the character read

And it's already C string that you can pass, without & because arrays decay to pointers to their first element它已经是 C 字符串,你可以传递,没有 & 因为 arrays 衰减到指向它们的第一个元素的指针

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM