It's funny when searching for examples on how to do something you end up getting results for posts you wrote a few days ago and not much else. I suppose that's a sign that I'm doing something bleeding edge and esoteric. Also props on dev.to for good SEO.
A quick hit for today, since apparently I not only accidentally started writing a book and accidentally started this mruby project, I also accidentally became the primary documenter for using mruby in practice. We learned how to create a Ruby class in C with mruby which stores arbitrary C data using the Data class type. What I want to do now is pass a Data instance as a parameter into another method. For example I'm pulling Win32 window management and Vulkan state into Ruby classes. Creating a VulkanState depends on a native window, in this case a Win32 window. The Ruby side is easy enough
@native_window = W32Window.new 'Foo', width: 1024, height: 768
@vulkan_state = VulkanState.new(@native_window)
Getting started with creating a VulkanState class is also typical
RClass *VulkanState_C = mrb_define_class(state, "VulkanState", state->object_class);
MRB_SET_INSTANCE_TT(VulkanState_C, MRB_TT_DATA);
mrb_define_method(state, VulkanState_C, "initialize",
VulkanState_initialize, MRB_ARGS_REQ(1));
It's extracting the Data type with mrb_get_args
which had me stumped for a while as I could not figure out how to get the right data type out. The documentation for mrb_get_args
states how to get a Data type argument
| `d` | data | void *, {mrb_data_type} const | 2nd argument will be used to check data type so it won't be modified; when `!` follows, the value may be `nil` |
First try is a normal mrb_value
mrb_value
VulkanState_initialize(mrb_state* state, mrb_value self) {
mrb_value gui_window;
mrb_get_args(state, "d", &gui_window, &W32Window_data_type);
Which creates some wild looking data pointers in gui_window
Next attempt is try pulling the data out with DATA_PTR
from the mrb_value
W32Window* window = reinterpret_cast<W32Window *>(DATA_PTR(gui_window));
Still wild data
Digging into the code, mrb_get_args
automatically pulls out and type casts the void *
for us using mrb_data_get_ptr
. Therefore pulling a Data type out doesn't require any extra work from our side.
W32Window_data* gui_window;
mrb_get_args(state, "d", &gui_window, &W32Window_data_type);
Now it's correct
That's all! A complete abstract example on receiving a Data type as a method argument
struct Foo_data {
uint32_t baz;
};
static const Foo_data_type = { "Foo", mrb_free };
mrb_value
Bar_get_foo(mrb_state* state, mrb_value* self) {
Foo_data *foo_data;
mrb_get_args(state, "d", &foo_data, &Foo_data_type);
return mrb_nil_value();
}
RClass *Foo = mrb_define_class(state, "Foo", state->object_class);
MRB_SET_INSTANCE_TT(Foo, MRB_TT_DATA);
RClass *Bar = mrb_define_class(state, "Bar", state->object_class);
mrb_define_method(state, Bar, "get_foo", Bar_get_foo, MRB_ARGS_REQ(1));
Top comments (0)