用于操作二进制数据的Ruby C-Extension

时间:2013-06-18 21:59:06

标签: ruby ruby-c-extension

我需要将Ruby与C函数接口,该函数在固定大小的缓冲区(16字节长度)上执行低级字节操作。

我还应该提一下,我正在使用Ruby 1.8.7,所以没有头痛,Ruby试图找出编码。

 void transmogrify(unsigned char *data_in, unsigned_char *data_out)
 {
   unsigned char buffer[16];
   for(i=0;i<16;i++) {
     buffer[i] = data_in[i] << 2;  // some low level operations on 8-bit values here
   }
   memcpy(data_out, buffer, sizeof(buffer));
 }        

如何在我的库中编写Ruby C接口代码,以便它能正确处理字符串中的二进制数据?例如它对固定长度输入字符串中的零字节是否健壮?

如果我使用StringValuePtr(),它会在零字节上中断。

 static VALUE mygem_transmogrify(VALUE self, VALUE input)
 {
   unsigned char output[16]
   if (TYPE(input) != T_STRING) { return Qnil; }  // make sure input is a String
   StringValuePtr(input);  // <--- THIS does not like zero bytes in the string
   transmogrify( (unsigned char *) RSTRING_PTR(input) , (unsigned char *) output);
   return rb_str_new( (char *) output, 16);
 }

我想从Ruby中调用它,如下所示:

input_string = File.read( 'somefile')       # reads 16 bytes binary
output = MyGem.transmogrify( input_string ) # output should be 16 bytes binary

 => ... in 'transmogrify': string contains null butye (ArgumentError)

1 个答案:

答案 0 :(得分:0)

我明白了:

 static VALUE mygem_transmogrify(VALUE self, VALUE input)
 {
   unsigned char output[16]
   if (TYPE(input) != T_STRING) { return Qnil; }  // make sure input is a String
   transmogrify( (unsigned char *) RSTRING(input)->ptr , (unsigned char *) output);
   return rb_str_new( (char *) output, 16);
 }

这不会破坏输入字符串中的零字节。