• Login
sketchucation logo sketchucation
  • Login
ℹ️ GoFundMe | Our friend Gus Robatto needs some help in a challenging time Learn More

Pass array to a c/c++ ruby extension

Scheduled Pinned Locked Moved Developers' Forum
6 Posts 3 Posters 2.1k Views
Loading More Posts
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • D Offline
    dacastror
    last edited by 3 Jul 2017, 21:21

    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)

    1 Reply Last reply Reply Quote 0
    • D Offline
      Dan Rathbun
      last edited by 4 Jul 2017, 11:10

      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

      I'm not here much anymore.

      1 Reply Last reply Reply Quote 0
      • D Offline
        Dan Rathbun
        last edited by 4 Jul 2017, 11:18

        @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.)

        I'm not here much anymore.

        1 Reply Last reply Reply Quote 0
        • D Offline
          dacastror
          last edited by 4 Jul 2017, 20:26

          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 Reply Last reply Reply Quote 0
          • A Offline
            Anton_S
            last edited by 4 Jul 2017, 22:52

            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.

            1 Reply Last reply Reply Quote 0
            • D Offline
              Dan Rathbun
              last edited by 5 Jul 2017, 19:45

              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.

              Link Preview Image
              SWIG - Wikipedia

              favicon

              (en.wikipedia.org)

              Link Preview Image
              SWIG Tutorial

              favicon

              (www.swig.org)

              Link Preview Image
              Simplified Wrapper and Interface Generator

              favicon

              (www.swig.org)

              I'm not here much anymore.

              1 Reply Last reply Reply Quote 0
              • 1 / 1
              1 / 1
              • First post
                1/6
                Last post
              Buy SketchPlus
              Buy SUbD
              Buy WrapR
              Buy eBook
              Buy Modelur
              Buy Vertex Tools
              Buy SketchCuisine
              Buy FormFonts

              Advertisement