Quantcast
Channel: Active questions tagged ruby - Stack Overflow
Viewing all articles
Browse latest Browse all 4619

How to call "unpack" on a string in ruby C-api?

$
0
0

I am trying to use the ruby C-api to call unpack on a ruby string.

Here is my current code:

#include "ruby.h"#include <stdio.h>#include <unistd.h>VALUE dangerous_func(unsigned char* buf) {    VALUE hello_world_str;    VALUE format_string;    hello_world_str = rb_str_new_cstr(buf); // Create ruby string from buffer.    format_string = rb_str_new_cstr("b8B8"); // Example format string.    printf("Before...\n");    rb_funcall(hello_world_str, rb_intern("unpack"), 1, format_string); // Pass the format string as argument.    printf("After...\n");    return Qnil; // Just return Qnil}// This is needed for rb_rescueVALUE error_func(VALUE stuff) {    return Qnil;}#define MAX_INPUT_SIZE 1000int main(int argc, char **argv) {    unsigned char input[MAX_INPUT_SIZE+1]; // Input buffer    int len;    memset(input, 0x00, MAX_INPUT_SIZE+1); // Zero out input buffer    ruby_setup();    ruby_sysinit(&argc, &argv);    RUBY_INIT_STACK;    ruby_init();    ruby_init_loadpath();    len = read(0, input, MAX_INPUT_SIZE);    rb_rescue(dangerous_func, input, error_func, Qnil); // Call the function    ruby_finalize(); // Cleanup    return 0;}

After testing the code with the input aa, it just prints Before... and exits, therefore it exits in the rb_funcall function.

I looked around the ruby codebase and in the string.c file, there are many method definitions for the string object, but none of which was unpack or pack:

// ...    rb_define_method(rb_cString, "sub", rb_str_sub, -1);    rb_define_method(rb_cString, "gsub", rb_str_gsub, -1);    rb_define_method(rb_cString, "chop", rb_str_chop, 0);    rb_define_method(rb_cString, "chomp", rb_str_chomp, -1);    rb_define_method(rb_cString, "strip", rb_str_strip, 0);    rb_define_method(rb_cString, "lstrip", rb_str_lstrip, 0);    rb_define_method(rb_cString, "rstrip", rb_str_rstrip, 0);    rb_define_method(rb_cString, "delete_prefix", rb_str_delete_prefix, 1);    rb_define_method(rb_cString, "delete_suffix", rb_str_delete_suffix, 1);    rb_define_method(rb_cString, "sub!", rb_str_sub_bang, -1);    rb_define_method(rb_cString, "gsub!", rb_str_gsub_bang, -1);    rb_define_method(rb_cString, "chop!", rb_str_chop_bang, 0);    rb_define_method(rb_cString, "chomp!", rb_str_chomp_bang, -1);    rb_define_method(rb_cString, "strip!", rb_str_strip_bang, 0);    rb_define_method(rb_cString, "lstrip!", rb_str_lstrip_bang, 0);    rb_define_method(rb_cString, "rstrip!", rb_str_rstrip_bang, 0);    rb_define_method(rb_cString, "delete_prefix!", rb_str_delete_prefix_bang, 1);    rb_define_method(rb_cString, "delete_suffix!", rb_str_delete_suffix_bang, 1);    rb_define_method(rb_cString, "tr", rb_str_tr, 2);    rb_define_method(rb_cString, "tr_s", rb_str_tr_s, 2);    rb_define_method(rb_cString, "delete", rb_str_delete, -1);    rb_define_method(rb_cString, "squeeze", rb_str_squeeze, -1);    rb_define_method(rb_cString, "count", rb_str_count, -1);    rb_define_method(rb_cString, "tr!", rb_str_tr_bang, 2);    rb_define_method(rb_cString, "tr_s!", rb_str_tr_s_bang, 2);    rb_define_method(rb_cString, "delete!", rb_str_delete_bang, -1);    rb_define_method(rb_cString, "squeeze!", rb_str_squeeze_bang, -1);    rb_define_method(rb_cString, "each_line", rb_str_each_line, -1);    rb_define_method(rb_cString, "each_byte", rb_str_each_byte, 0);    rb_define_method(rb_cString, "each_char", rb_str_each_char, 0);    rb_define_method(rb_cString, "each_codepoint", rb_str_each_codepoint, 0);    rb_define_method(rb_cString, "each_grapheme_cluster", rb_str_each_grapheme_cluster, 0);    rb_define_method(rb_cString, "sum", rb_str_sum, -1);    rb_define_method(rb_cString, "slice", rb_str_aref_m, -1);    rb_define_method(rb_cString, "slice!", rb_str_slice_bang, -1);    rb_define_method(rb_cString, "partition", rb_str_partition, 1);    rb_define_method(rb_cString, "rpartition", rb_str_rpartition, 1);    rb_define_method(rb_cString, "encoding", rb_obj_encoding, 0); /* in encoding.c */    rb_define_method(rb_cString, "force_encoding", rb_str_force_encoding, 1);    rb_define_method(rb_cString, "b", rb_str_b, 0);    rb_define_method(rb_cString, "valid_encoding?", rb_str_valid_encoding_p, 0);    rb_define_method(rb_cString, "ascii_only?", rb_str_is_ascii_only_p, 0);    /* define UnicodeNormalize module here so that we don't have to look it up */    mUnicodeNormalize          = rb_define_module("UnicodeNormalize");    id_normalize               = rb_intern_const("normalize");    id_normalized_p            = rb_intern_const("normalized?");    rb_define_method(rb_cString, "unicode_normalize", rb_str_unicode_normalize, -1);    rb_define_method(rb_cString, "unicode_normalize!", rb_str_unicode_normalize_bang, -1);    rb_define_method(rb_cString, "unicode_normalized?", rb_str_unicode_normalized_p, -1);    rb_fs = Qnil;    rb_define_hooked_variable("$;", &rb_fs, 0, rb_fs_setter);    rb_define_hooked_variable("$-F", &rb_fs, 0, rb_fs_setter);    rb_gc_register_address(&rb_fs);    rb_cSymbol = rb_define_class("Symbol", rb_cObject);    rb_include_module(rb_cSymbol, rb_mComparable);    rb_undef_alloc_func(rb_cSymbol);    rb_undef_method(CLASS_OF(rb_cSymbol), "new");    rb_define_singleton_method(rb_cSymbol, "all_symbols", sym_all_symbols, 0);    rb_define_method(rb_cSymbol, "==", sym_equal, 1);    rb_define_method(rb_cSymbol, "===", sym_equal, 1);    rb_define_method(rb_cSymbol, "inspect", sym_inspect, 0);    rb_define_method(rb_cSymbol, "name", rb_sym2str, 0); /* in symbol.c */    rb_define_method(rb_cSymbol, "to_proc", rb_sym_to_proc, 0); /* in proc.c */    rb_define_method(rb_cSymbol, "succ", sym_succ, 0);    rb_define_method(rb_cSymbol, "next", sym_succ, 0);    rb_define_method(rb_cSymbol, "<=>", sym_cmp, 1);    rb_define_method(rb_cSymbol, "casecmp", sym_casecmp, 1);    rb_define_method(rb_cSymbol, "casecmp?", sym_casecmp_p, 1);    rb_define_method(rb_cSymbol, "=~", sym_match, 1);    rb_define_method(rb_cSymbol, "[]", sym_aref, -1);    rb_define_method(rb_cSymbol, "slice", sym_aref, -1);    rb_define_method(rb_cSymbol, "length", sym_length, 0);// ...

there is also the pack.rb file:

class Array  #  call-seq:  #    pack(template, buffer: nil) -> string  #  #  Formats each element in +self+ into a binary string; returns that string.  #  See {Packed Data}[rdoc-ref:packed_data.rdoc].  def pack(fmt, buffer: nil)    Primitive.pack_pack(fmt, buffer)  endendclass String  # call-seq:  #   unpack(template, offset: 0) -> array  #  #  Extracts data from +self+, forming objects that become the elements of a new array;  #  returns that array.  #  See {Packed Data}[rdoc-ref:packed_data.rdoc].  def unpack(fmt, offset: 0)    Primitive.pack_unpack(fmt, offset)  end  # call-seq:  #   unpack1(template, offset: 0) -> object  #  #  Like String#unpack, but unpacks and returns only the first extracted object.  #  See {Packed Data}[rdoc-ref:packed_data.rdoc].  def unpack1(fmt, offset: 0)    Primitive.pack_unpack1(fmt, offset)  endend

and it seems that we should call pack_unpack instead, but neither pack_unpack exists in the string method definitions. I tried to replace the unpack method with other methods and it works as intended, but when I try to use unpack, it exits before execution can get to the After... line.

So, my question is, how do I call the unpack method on a ruby string in ruby C-api?

I want the C code to be basically the same as this:

puts "Before..."(ARGF.read).unpack("b8B8")puts "After..."

but just in C.


Viewing all articles
Browse latest Browse all 4619

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>