Creé el método Ruby en C usando Ruby API que recibe 3 argumentos de cadena:
VALUE cache_class = rb_define_class_under(class, CACHE_CLASS_NAME, rb_cObject); rb_define_method(cache_class, "cache_test_result", cache_test_result, 3);En test.rb llamé al método:
Cache.new.cache_test_result("str1", "str2", "str3")Y la función C cache_test_result funciona de forma extraña:
VALUE cache_test_result(VALUE str1, VALUE str2, VALUE str3) { int rstr1_len = RSTRING_LEN(str1) + 1; char buf_str1[rstr1_len]; strlcpy(buf_str1, RSTRING_PTR(str1), rstr1_len); int rstr2_len = RSTRING_LEN(str2) + 1; char buf_str2[rstr2_len]; strlcpy(buf_str2, RSTRING_PTR(str2), rstr2_len); int rstr3_len = RSTRING_LEN(str3) + 1; char buf_str3[rstr3_len]; strlcpy(buf_str3, RSTRING_PTR(str3), rstr3_len); printf("buf_str1: %s\n", buf_str1); printf("buf_str2: %s\n", buf_str2); printf("buf_str3: %s\n", buf_str3); }salida de esta función:
buf_str1: buf_str2: str1 buf_str3: str2¿Por qué args ha compensado...?
El primer argumento de la función C es el yo, el resto son los argumentos del método.
Lo que significa que necesita ajustar el prototipo de función y agregar un parámetro adicional, por ejemplo:
VALUE cache_test_result(VALUE self, VALUE str1, VALUE str2, VALUE str3) { Y dado que un objeto C de tipo VALUE puede ser cualquier cosa (una cadena Ruby, un número entero o cero), nunca use RSTRING_{PTR,LEN} y funciones similares (macro) sin estar seguro de su tipo Ruby. En su lugar, puede usar Check_Type , StringValuePtr o StringValueCStr según el caso de uso.
Su ejemplo podría reescribirse como:
VALUE cache_test_result(VALUE self, VALUE str1, VALUE str2, VALUE str3) { // Check if each value is a Ruby string // (or can be implicitly converted to one) and // return a pointer to its underlying C string. // It it also checked if the Ruby string contains NUL. // If any check fails an exception is raised. const char *buf_str1 = StringValueCStr(str1); const char *buf_str2 = StringValueCStr(str2); const char *buf_str3 = StringValueCStr(str3); // print each underlying C string printf("buf_str1: %s\n", buf_str1); printf("buf_str2: %s\n", buf_str2); printf("buf_str3: %s\n", buf_str3); }