Pass array to a c/c++ ruby extension

Pass array to a c/c++ ruby extension

Postby dacastror » Mon Jul 03, 2017 10:21 pm

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)
0

dacastror 
 

Re: Pass array to a c/c++ ruby extension

Postby Anton_S » Mon Jul 03, 2017 10:57 pm

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:

Code: Select all
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:
Code: Select all
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:
Code: Select all
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.
1
Last edited by Anton_S on Tue Jul 04, 2017 11:52 pm, edited 1 time in total.

Anton_S 
PluginStore Author
PluginStore Author
 

Re: Pass array to a c/c++ ruby extension

Postby Dan Rathbun » Tue Jul 04, 2017 12:10 pm

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):

http://media.pragprog.com/titles/ruby3/ext_ruby.pdf
0
    I'm not here much anymore. But a PM will fire email notifications.
    User avatar
    Dan Rathbun 
    PluginStore Author
    PluginStore Author
     

    Re: Pass array to a c/c++ ruby extension

    Postby Dan Rathbun » Tue Jul 04, 2017 12:18 pm

    Anton_S wrote: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:
    Code: Select all
    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.)
    0
      I'm not here much anymore. But a PM will fire email notifications.
      User avatar
      Dan Rathbun 
      PluginStore Author
      PluginStore Author
       

      Re: Pass array to a c/c++ ruby extension

      Postby dacastror » Tue Jul 04, 2017 9:26 pm

      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?
      1

      dacastror 
       

      Re: Pass array to a c/c++ ruby extension

      Postby Dan Rathbun » Wed Jul 05, 2017 8:45 pm

      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.

      https://en.wikipedia.org/wiki/SWIG

      http://www.swig.org/tutorial.html

      http://www.swig.org/
      0
        I'm not here much anymore. But a PM will fire email notifications.
        User avatar
        Dan Rathbun 
        PluginStore Author
        PluginStore Author
         

        SketchUcation One-Liner Adverts

        by Ad Machine » 5 minutes ago



        Ad Machine 
        Robot
         



         

        Return to Developers' Forum

        Who is online

        Users browsing this forum: sallyyyychan and 4 guests

        Visit our sponsors: