Pass array to a c/c++ ruby extension
-
Hi, I am creating my first c / c ++ ruby extension with the help of the examples found in: https://github.com/SketchUp/ruby-c-extension-examples
I have been able to modify these examples successfully. But now I want to pass an array of ruby to C ++ like the following:[ [1, 2, 3], [2 ,3, 4], [4, 5, 6], ... ]
That correspond to the 3d coordinates of some points, and I want to bring back to ruby another similar array. For the moment I have only been successful with strings and with floats using the example of the repository called SUEX_UsingSWIG, but I do not know how it is done for arrays. Thank you in advance for your help.
(I use google translator, sorry for the mistakes in the translation) -
Read this book for that kind of normal Ruby C extension stuff:
This is the Pragmatic Programmer's Guide to Extending Ruby (for v1.9.2)
by Dave Thomas.
(A companion to the good ol' "Pick Axe" Pragmatic Programmer's Guide): -
@anton_s said:
Note: I did not check this code for typos, so it's up to you to fix it (if there are any).
I see one. The Ruby initiator function should begin:
void Init_some_lib() { // ...
where the name of the library file is exactly "some_lib" (with whatever the platform shared library extension is, ie ".so", ".dll", ".bundle". etc.)
-
Anton thank you very much, your code worked very well when I entered it in SUEX_HelloWorld.cpp from the HelloWorld example of the repository, I just changed some names in the project to match everything and it worked perfectly .
Thanks a lot for the pdf Dan, it's very interesting.
I still have one question, how could I do this in the example called SUEX_UsingSWIG ?, I observed the Swig documentation and the pdf that shows Dan, but I could not see how this is done. Any idea?
-
Everything you pass to ruby and obtain from ruby is in a form of pointers (except for fixed numbers and some literals). So, an array passed to a c extension would be in a form of a pointer. Here is how you would process it:
static VALUE process_array(VALUE self, VALUE v_array) { // Ensure the data passed is an array Check_Type(v_array, T_ARRAY); // Process the array unsigned int array_size = (unsigned int)RARRAY_LEN(v_array); for (unsigned int i = 0; i < array_size; ++i) { VALUE v_internal_array = rb_ary_entry(v_array, i); // Ensure the internal value is an array Check_Type(v_internal_array, T_ARRAY); // Process the internal array unsigned int internal_array_size = (unsigned int)RARRAY_LEN(v_internal_array); for (unsigned int j = 0; j < internal_array_size; ++j) { VALUE v_res = rb_ary_entry(v_array, i); int res = NUM2INT(v_res); // Do something } } // Return something (nil in this case) return Qnil; }
If you want to process an array of Geom::Point3d/Geom::Vector3d objects, you have to access them by their x, y, z interns:
static VALUE process_array_of_points(VALUE self, VALUE v_array) { // Ensure the data passed is an array Check_Type(v_array, T_ARRAY); // Process the array unsigned int array_size = (unsigned int)RARRAY_LEN(v_array); for (unsigned int i = 0; i < array_size; ++i) { VALUE v_point = rb_ary_entry(v_array, i); double x = rb_num2dbl(rb_funcall(v_point, rb_intern("x"), 0)); double y = rb_num2dbl(rb_funcall(v_point, rb_intern("y"), 0)); double z = rb_num2dbl(rb_funcall(v_point, rb_intern("z"), 0)); // Do something } // Return something (nil in this case) return Qnil; }
Accessing even an Array object with x,y,z interns will work too, because SketchUp adds these functions to an Array class. So, this second function will work with an array of array, array of Point3d objects, and array of Vector3d objects.
And then of course, you will have to link them with Ruby in the initiator function:
void Init_some_lib() { VALUE mDacastror = rb_define_module("Dacastror"); rb_define_module_function(mDacastror, "process_array", VALUEFUNC(process_array), 1); rb_define_module_function(mDacastror, "process_array_of_points", VALUEFUNC(process_array_of_points), 1); }
Note: I did not check this code for typos, so it's up to you to fix it (if there are any).
Here are a few links to Ruby c++ extension guides:
http://clalance.blogspot.com/2011/01/writing-ruby-extensions-in-c-part-9.html
https://silverhammermba.github.io/emberb/c/If you search the web, there are plenty of more links on that.
-
Never could understand SWIG much. Cryptic interface language.
If you intended to write a library that needs interfaces in multiple scripting languages, then SWIG might lessen the workload. Or if you are wanting a Ruby interface for some library already written that has SWIG interface files, then again I can see using SWIG.But for an extension that will be written specifically for SketchUp, since it only uses Ruby, I cannot see much use for SWIG.
Advertisement