ruby / fiddle

A libffi wrapper for Ruby.
BSD 2-Clause "Simplified" License
154 stars 37 forks source link

Question: When passing a char as a function argument, should I pass the number obtained by calling the string's ord method? #96

Closed kojix2 closed 1 year ago

kojix2 commented 2 years ago

Hi! I have a question about c char.

https://github.com/andlabs/libui/blob/fea45b2d5b75839be0af9acc842a147c5cba9295/ui.h#L767

c function

void uiOpenTypeFeaturesAdd(uiOpenTypeFeatures *otf, char a, char b, char c, char d, uint32_t value);

ruby method

extern 'void uiOpenTypeFeaturesAdd(uiOpenTypeFeatures *otf, char a, char b, char c, char d, uint32_t value)'

I wonder if I should call ord like this?

LibUI::FFI.uiOpenTypeFeaturesAdd(otf, 'l'.ord, 'i'.ord, 'g'.ord, 'a'.ord, 0)

Thank you.

kou commented 2 years ago

Yes. Because char is signed 8 bit integer in C.

But we can pass one byte string directly with the following change:

diff --git a/ext/fiddle/conversions.c b/ext/fiddle/conversions.c
index 6e0ce36..f7b0b75 100644
--- a/ext/fiddle/conversions.c
+++ b/ext/fiddle/conversions.c
@@ -209,7 +209,11 @@ rb_fiddle_value_to_generic(int type, VALUE *src, fiddle_generic *dst)
    dst->pointer = NUM2PTR(rb_Integer(*src));
    break;
       case TYPE_CHAR:
-   dst->schar = (signed char)NUM2INT(*src);
+        if (RB_TYPE_P(*src) == RUBY_T_STRING && RSTRING_LEN(*src) == 1) {
+            dst->schar = RSTRING_PTR(*src)[0];
+        } else {
+            dst->schar = (signed char)NUM2INT(*src);
+        }
    break;
       case -TYPE_CHAR:
    dst->uchar = (unsigned char)NUM2UINT(*src);
kojix2 commented 2 years ago

Thanks. I hadn't thought about changing the Fiddle. However, I understand what you are saying. Certainly this is something that many people would do on the Ruby code side .

kojix2 commented 2 years ago

My issue has been resolved, but as a suggestion for possible changes, shall I leave this issue open?

kou commented 2 years ago

Yes, please.