New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Way to wrap C language structure? #9
Comments
|
The following is the code from (undisclosed) socket extension: #include "mruby/data.h"
static void
sock_free(mrb_state *mrb, void *p)
{
close((int)p);
}
static const struct mrb_data_type sock_data_type = {
"socket", sock_free,
};
VALUE
rsock_new_sock(mrb_state *mrb, struct RClass *c, int fd)
{
return mrb_obj_value(Data_Wrap_Struct(mrb, c, &sock_data_type, (void*)fd));
}Hope this helps to grab the code structure. |
|
Thank you. |
|
Are you going to add alloc_func? |
|
use MRB_SET_INSTANCE_TT(c, t) to specify instance object type. See src/array.c for example. |
|
I'll look into it. thanks. |
|
Is the Socket extension available anywhere? I don't want to reinvent the wheel.. |
|
https://github.com/iij/mruby provided extended version mruby. it's included TCPSocket and UNIXSocket. |
|
@masuidrive, from what I understand, this will not be included in mruby as socket handling is not platform independent. Thanks for the link! |
The following code crashes without this change:
def a
[1].each do
[2].each do
[3].each do
raise "XXX"
end
end
end
end
begin
a
rescue => exception
GC.start
exception.backtrace
end
GDB backtrace:
Program received signal SIGSEGV, Segmentation fault.
strlen () at ../sysdeps/x86_64/strlen.S:106
106 ../sysdeps/x86_64/strlen.S: No such file or directory.
(gdb) bt
#0 strlen () at ../sysdeps/x86_64/strlen.S:106
#1 0x00000000004252cd in mrb_str_new_cstr (mrb=0x69f010,
p=0x101 <error: Cannot access memory at address 0x101>)
at mruby/src/string.c:290
#2 0x00000000004183fe in get_backtrace_i (mrb=0x69f010, loc=0x7fffffffd940,
data=0x6a7410) at mruby/src/backtrace.c:72
#3 0x0000000000418793 in output_backtrace (mrb=0x69f010, ciidx=8,
pc0=0x71940c, func=0x4183af <get_backtrace_i>, data=0x6a7410)
at mruby/src/backtrace.c:140
#4 0x0000000000418862 in exc_output_backtrace (mrb=0x69f010, exc=0x6a5be0,
func=0x4183af <get_backtrace_i>, stream=0x6a7410)
at mruby/src/backtrace.c:157
#5 0x000000000041894c in mrb_exc_backtrace (mrb=0x69f010, self=...)
at mruby/src/backtrace.c:199
#6 0x000000000040dbaf in mrb_context_run (mrb=0x69f010, proc=0x6a61b0,
self=..., stack_keep=0) at mruby/src/vm.c:1126
#7 0x00000000004131d8 in mrb_toplevel_run_keep (mrb=0x69f010, proc=0x6a61b0,
stack_keep=0) at mruby/src/vm.c:2422
#8 0x000000000043a46c in load_exec (mrb=0x69f010, p=0x6f6450, c=0x6c9320)
at mruby/mrbgems/mruby-compiler/core/parse.y:5619
#9 0x000000000043a4e2 in mrb_load_file_cxt (mrb=0x69f010, f=0x6f61f0,
c=0x6c9320)
at mruby/mrbgems/mruby-compiler/core/parse.y:5628
#10 0x0000000000402466 in main (argc=2, argv=0x7fffffffe438)
at mruby/mrbgems/mruby-bin-mruby/tools/mruby/mruby.c:222
|
In the example: So that is mapped to the And what does I've written Ruby C Extensions before, for normal ruby, but I'm confused to how to do this for mruby. For normal ruby you have separate functions for allocation and initialization. For instance, this example from http://silverhammermba.github.io/emberb/c/#data - how does one translate that into mruby? (I've been looking at the source for mruby and the gems it ship, but I struggle to understand what is going on.) |
|
Looking at This one uses |
Neither. It's just an internal function. In mruby all C functions implementing Ruby methods must have the type
To tell mruby that instances of class
You have to do the allocations in
It isn't documented yet. But it's just a shortcut for setting both the data pointer and type. See |
https://gist.github.com/cremno/a75a41bee003077d9a01 (untested and it's an example anyway) |
|
Thank you so much for your response and code snippet. Btw, checking |
|
In Ruby A helper function might be useful though : mrb_int *data = (mrb_int*)DATA_PTR(self);
if (data) foo_free(mrb, data);
mrb_data_init(self, NULL, &foo_data_type);Would become: mrb_int *data; // for later?
mrb_data_foobar(self, &foo_data_type); |
|
It's unfortunate that the |
|
It's inherited from CRuby, but maybe we should rename it to RDATA_PTR() to avoid potential name clash and for consistency. |
|
Well, let's not inherit cruft from CRuby then ? ;) |
|
When should one use |
|
Whenever you create RData object. To use RDATA_PTR, you have to get RData object first. |
|
Thanks for confirming. |
|
|
|
I see - so |
|
Well, if // mrb_type(self) == MRB_TT_DATA because of MRB_SET_INSTANCE_TT(klass, MRB_TT_DATA)
mrb_int *data = DATA_PTR(self); // DATA_TYPE(self) == NULL; can't and don't need to care
if (data) foo_free(mrb, data);
mrb_data_init(self, NULL, &foo_data_type); // DATA_TYPE(self) = &foo_data_type
mrb_int val;
mrb_get_args(mrb, "i", &val);
data = mrb_malloc(mrb, sizeof *data);
*data = val;
DATA_PTR(self) = data; // don't need to care (correct data type)If you're writing a method that expects a data object with a specific data type, then you need to use There's also Take a look at the source code of the mruby-time gem if you haven't yet. You really don't have to (fully) understand it but it's a decent example how the data API should be used. Maybe somebody else knows a better (simpler) example. |
|
Thank you very much. I think that going back to |
OpenSolaris/Illumos defines a "sun" constant...
Suppress compiler warning [-Wpointer-sign]
### Example
##### example.rb
```ruby
h = {}
(1..17).each{h[_1] = _1}
(1..16).each{h.delete(_1)}
h.rehash
```
##### ASAN report
```console
$ bin/mruby example.rb
==52587==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x602000006998 at pc 0x55a29cddf96b bp 0x7fff7b1b1720 sp 0x7fff7b1b1710
READ of size 4 at 0x602000006998 thread T0
#0 0x55a29cddf96a in ib_it_next /mruby/src/hash.c:639
mruby#1 0x55a29cde2ca2 in ht_rehash /mruby/src/hash.c:900
mruby#2 0x55a29cde379f in h_rehash /mruby/src/hash.c:996
mruby#3 0x55a29cde7f3d in mrb_hash_rehash /mruby/src/hash.c:1735
mruby#4 0x55a29ce77b62 in mrb_vm_exec /mruby/src/vm.c:1451
mruby#5 0x55a29ce5fa88 in mrb_vm_run /mruby/src/vm.c:981
mruby#6 0x55a29ceb87e1 in mrb_top_run /mruby/src/vm.c:2874
mruby#7 0x55a29cf36bdf in mrb_load_exec mrbgems/mruby-compiler/core/parse.y:6805
mruby#8 0x55a29cf36f25 in mrb_load_detect_file_cxt mrbgems/mruby-compiler/core/parse.y:6848
mruby#9 0x55a29cdba0a2 in main /mruby/mrbgems/mruby-bin-mruby/tools/mruby/mruby.c:347
mruby#10 0x7f24ef43b0b2 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x270b2)
mruby#11 0x55a29cdb4a6d in _start (/mruby/bin/mruby+0x2a3a6d)
0x602000006998 is located 0 bytes to the right of 8-byte region [0x602000006990,0x602000006998)
allocated by thread T0 here:
#0 0x7f24f01cfffe in __interceptor_realloc (/lib/x86_64-linux-gnu/libasan.so.5+0x10dffe)
mruby#1 0x55a29ceb9440 in mrb_default_allocf /mruby/src/state.c:68
mruby#2 0x55a29cdba747 in mrb_realloc_simple /mruby/src/gc.c:228
mruby#3 0x55a29cdba928 in mrb_realloc /mruby/src/gc.c:242
mruby#4 0x55a29cde12e5 in ht_init /mruby/src/hash.c:749
mruby#5 0x55a29cde2b8e in ht_rehash /mruby/src/hash.c:897
mruby#6 0x55a29cde379f in h_rehash /mruby/src/hash.c:996
mruby#7 0x55a29cde7f3d in mrb_hash_rehash /mruby/src/hash.c:1735
mruby#8 0x55a29ce77b62 in mrb_vm_exec /mruby/src/vm.c:1451
mruby#9 0x55a29ce5fa88 in mrb_vm_run /mruby/src/vm.c:981
mruby#10 0x55a29ceb87e1 in mrb_top_run /mruby/src/vm.c:2874
mruby#11 0x55a29cf36bdf in mrb_load_exec mrbgems/mruby-compiler/core/parse.y:6805
mruby#12 0x55a29cf36f25 in mrb_load_detect_file_cxt mrbgems/mruby-compiler/core/parse.y:6848
mruby#13 0x55a29cdba0a2 in main /mruby/mrbgems/mruby-bin-mruby/tools/mruby/mruby.c:347
mruby#14 0x7f24ef43b0b2 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x270b2)
```
add conf.enable_test into build_config.rb
Where is function to embed wrapped object that like ruby's
Data_Make_Struct. Or way to add trick to wrap it?Thanks.
The text was updated successfully, but these errors were encountered: