• Login
sketchucation logo sketchucation
  • Login
โ„น๏ธ Licensed Extensions | FredoBatch, ElevationProfile, FredoSketch, LayOps, MatSim and Pic2Shape will require license from Sept 1st More Info

Testing Ruby VALUES in C-extension.

Scheduled Pinned Locked Moved Developers' Forum
69 Posts 6 Posters 3.2k Views 6 Watching
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.
  • T Offline
    tt_su
    last edited by 21 Aug 2014, 13:32

    Check out the VS2013 branch in my private fork:
    https://github.com/thomthom/ruby-c-extension-examples/tree/VS2013

    I just checked in a commit with some changes that should make it compile.
    https://github.com/thomthom/ruby-c-extension-examples/commit/0d4090d47fc563754b57efcc003114e3973cabc7

    There might be other changes required as you pull in more libraries though.

    1 Reply Last reply Reply Quote 0
    • J Offline
      jolran
      last edited by 21 Aug 2014, 13:48

      Exellent!!

      @unknownuser said:

      But if I recall, one of the things where that Ruby define a "inline" macro that conflicts with VS2013.

      Yeah, that's exactly what's happening. That also leads to hundreds of other sub-error messages.

      I give it a try and report back!

      Thanks again. ๐Ÿ‘

      1 Reply Last reply Reply Quote 0
      • J Offline
        jolran
        last edited by 21 Aug 2014, 14:23

        It worked! ๐Ÿ˜ To make it simple for myself, I just launched your version..
        I can now launch the debugger and Sketchup's correct version launch, all good to go.

        Just some rookie notes: (things that may be taken for granted by proffesionals ๐Ÿ˜‰ )

        • Working with the ruby console in debugg-mode, theres no need to require the module. Just call the C-extension functions.

        * To switch release-version go into Configuration Manager (See pic below). One might think changing Release from 2.0 to 1.8 in the dropdown meny changes the project settings, But it don't(?). Not for me it diden't..

        EDIT: Scratch that. It worked after a project clean.

        Thanks a million Thomthom!! Now it's only the small detail of adding code, left to do.


        1 Reply Last reply Reply Quote 0
        • T Offline
          tt_su
          last edited by 21 Aug 2014, 14:32

          @jolran said:

          Just some rookie notes: (things that may be taken for granted by proffesionals ๐Ÿ˜‰ )

          • Working with the ruby console in debugg-mode, theres no need to require the module. Just call the C-extension functions.

          That's due to how the project is set up to launch SketchUp with the loading-helper that loads the extension. It's not automatic unless you configured the project to do so.
          We need to add more info for the project. Please fill out issues on the GitHub bug tracker to help us keep track of this.

          @jolran said:

          • To switch release-version go into Configuration Manager (See pic below). One might think changing Release from 2.0 to 1.8 in the dropdown meny changes the project settings, But it don't(?). Not for me it diden't..

          When you change from the drop down menu that will change what is built. In order to build multiple go BUILT > Batch Build
          2014-08-21_16h40_40.png

          1 Reply Last reply Reply Quote 0
          • T Offline
            tt_su
            last edited by 21 Aug 2014, 14:33

            Ah, post edited... ๐Ÿ˜„

            1 Reply Last reply Reply Quote 0
            • J Offline
              jolran
              last edited by 21 Aug 2014, 14:55

              Yeah, sorry about that.
              I was to exited. ๐Ÿ˜„

              1 Reply Last reply Reply Quote 0
              • T Offline
                tt_su
                last edited by 22 Aug 2014, 08:10

                I might have mucked up the debug config with that VS2013 branch... Just looked at the diff of changes and something looks amiss. Just so you are aware.
                I'm not sure I have time until next week to look into that.

                1 Reply Last reply Reply Quote 0
                • J Offline
                  jolran
                  last edited by 22 Aug 2014, 10:51

                  Ok, thanks for telling.

                  I havent tested it much yet. Will dig in more intensly after the weekend.
                  Anyway it seams to be working correctly when just calling functions from the C module in the Ruby console.

                  1 Reply Last reply Reply Quote 0
                  • J Offline
                    jolran
                    last edited by 29 Aug 2014, 19:08

                    So I finally managed to bring in 100 000 points convert them to C++ class and then convert back to Sketchup Point3d objects.

                    Timing the response back in Alex S-Ruby console clocks ~ 0.50 which is amazingly fast.
                    Did some other tests, bloody hell it's blitz.. ๐Ÿ˜„

                    However if I clock a new "puts time" in the row after the C -callback. it gets increasingly
                    slower for each C-functioncall. ๐Ÿ˜•
                    C-callback response still clocks about the same each time..

                    Is it the Ruby garbage collector running ? Adding this amount of points aught to slow Sketchup down, I know..

                    So I take it one cannot rely on C-response when things are "ready" to go forth in Ruby ?
                    For ex if I expect an array as responce will there be an error in following code.
                    Or does not following code execute until the array is ready ?
                    (havent tested stuff on so many points yet)

                    I don't think I'm creating a memory leak in C++ since I have seen the destructor activate during some tests. And this test is done within 1 function so.. Points in points out..

                    Note: I did this in debug-mode(SU 2013), so maybe that affects threading or something.

                    1 Reply Last reply Reply Quote 0
                    • T Offline
                      tt_su
                      last edited by 31 Aug 2014, 12:40

                      @jolran said:

                      Timing the response back in Alex S-Ruby console clocks ~ 0.50 which is amazingly fast.
                      Did some other tests, bloody hell it's blitz.. ๐Ÿ˜„

                      @jolran said:

                      Note: I did this in debug-mode(SU 2013), so maybe that affects threading or something.

                      Debug builds are a lot slower than release as it execute a lot more debug code and doesn't have any optimizations enabled.

                      @jolran said:

                      However if I clock a new "puts time" in the row after the C -callback. it gets increasingly
                      slower for each C-functioncall. ๐Ÿ˜•
                      C-callback response still clocks about the same each time..

                      Is it the Ruby garbage collector running ? Adding this amount of points aught to slow Sketchup down, I know..

                      Hm... not sure. Might be. When I run performance tests in Ruby I tend to call GC.start at the beginning of my profiling to ensure the GC is reset before each test. Otherwise you have no idea when it will trigger.

                      @jolran said:

                      So I take it one cannot rely on C-response when things are "ready" to go forth in Ruby ?
                      For ex if I expect an array as responce will there be an error in following code.
                      Or does not following code execute until the array is ready ?
                      (havent tested stuff on so many points yet)

                      I don't think I'm creating a memory leak in C++ since I have seen the destructor activate during some tests. And this test is done within 1 function so.. Points in points out..

                      Your tests, does it only create Point3ds, or are you also creating and erasing geometry?

                      1 Reply Last reply Reply Quote 0
                      • J Offline
                        jolran
                        last edited by 31 Aug 2014, 16:06

                        Hi Thomas.

                        For that test I was sending in Ruby array with Sketchup Point3d's to a C++ function.
                        That function converted Ruby points to a simple C++ class representing Point3d.
                        That same function also converted back the C++ points to Sketchup Points.
                        So the return VALUE was a Ruby array of those points.
                        Not very useful, but interesting. Got to start somewhere...

                        I use vectors as containers in C++, don't know if that is the way to go with Ruby C++-extensions. Vectors seam to be quite used though..
                        Do you use maps with Ruby hashes ? I havent tested yet. Vectors seams more flexible.

                        What you say about Debug builds seams to hold true.
                        I managed to create an implementation for the points-indexing-triangulation I was talking about earlier, and ran that in my plugin compiled. Really fast compared to the Ruby version ๐Ÿ˜„
                        It still has some quirks and needs refinements, but it was good enough to make a realistic comparison.

                        @unknownuser said:

                        When I run performance tests in Ruby I tend to call GC.start at the beginning of my profiling to ensure the GC is reset before each test. Otherwise you have no idea when it will trigger

                        Ahhh yes. That's smart. Will try that, thanks.

                        Edit: Ehh duh! I wasent aware one could create breakpoints and step into the code while debugging in Sketchup. Most useful ๐Ÿ’š

                        1 Reply Last reply Reply Quote 0
                        • T Offline
                          tt_su
                          last edited by 1 Sept 2014, 08:40

                          @jolran said:

                          I use vectors as containers in C++, don't know if that is the way to go with Ruby C++-extensions. Vectors seam to be quite used though..
                          Do you use maps with Ruby hashes ? I havent tested yet. Vectors seams more flexible.

                          Yes, vectors are your usual go-to container.
                          map and unordered_map is what one use instead of Ruby Hash. Unordered map is usually a little bit faster, but a C++11 feature.
                          set and unordered_set is similar to - surprise - Ruby Set. ๐Ÿ˜„

                          @jolran said:

                          Edit: Ehh duh! I wasent aware one could create breakpoints and step into the code while debugging in Sketchup. Most useful ๐Ÿ’š

                          ๐Ÿ˜„ One thing that cought me off guard is the breakpoints doesn't always work in Release due to compiler optimization. Visual Studio 2013 even has a nice profiler which let you get detailed profiling info of your C++ code. (Should do a quick tutorial on that once.)

                          Speaking of debuggers, you know taht from SU2014 you can hook up Ruby debuggers for Ruby code in SketchUp?
                          https://github.com/SketchUp/sketchup-ruby-debugger
                          It's so much nice to be able to set breakpoints and step than litter the code with puts.

                          1 Reply Last reply Reply Quote 0
                          • T Offline
                            tt_su
                            last edited by 1 Sept 2014, 08:43

                            Btw, when you create a vector where you know the final number of item, call reserve to allocate enough memory in advance as you then avoid expensive memory reallocation as you populate the array. Even if you have only a rough estimate it's ok.

                            You can do something similar C++ std::vector<>.reserve with the Ruby C API by calling rb_ary_new2. You provide the number of final elements and it will allocate enough memory of the object up front.

                            1 Reply Last reply Reply Quote 0
                            • J Offline
                              jolran
                              last edited by 1 Sept 2014, 10:14

                              @unknownuser said:

                              Visual Studio 2013 even has a nice profiler which let you get detailed profiling info of your C++ code. (Should do a quick tutorial on that once.)

                              Yes that would off course be very nice.

                              Realized this thread is staring to get really packed of usefull information. Unfortunately in some time it will be burried in the forum.

                              Maybe a C-extension sticky-thread or something similar wouldent hurt. Or maybe this old topic is being used for that purpose ?
                              http://sketchucation.com/forums/viewtopic.php?f=180%26amp;t=41077%26amp;p=363978

                              One might not feel inclined to post silly C++ questions in that old thread.
                              Something like "Ruby C extensions for dummies" would be more approprioate. ๐Ÿ˜„

                              1 Reply Last reply Reply Quote 0
                              • J Offline
                                jolran
                                last edited by 1 Sept 2014, 12:24

                                @unknownuser said:

                                One thing that cought me off guard is the breakpoints doesn't always work in Release due to compiler optimization. Visual Studio 2013 even has a nice profiler which let you get detailed profiling info of your C++ code. (Should do a quick tutorial on that once.)

                                Speaking of debuggers, you know taht from SU2014 you can hook up Ruby debuggers for Ruby code in SketchUp?
                                https://github.com/SketchUp/sketchup-ruby-debugger
                                It's so much nice to be able to set breakpoints and step than litter the code with puts.

                                Well this keeps gets better and better. I did not know that.
                                Have been sending puts to ruby console from C++ but that wont work when stepping over code, so this sounds great.

                                @unknownuser said:

                                You can do something similar C++ std::vector<>.reserve with the Ruby C API by calling rb_ary_new2. You provide the number of final elements and it will allocate enough memory of the object up front.

                                Handy! I do a lot of conversions so that will help. I'm not in a mode of optimizing code yet, but suppose best practices are worth picking up at an early stage. ๐Ÿ˜„

                                I'm experiencing some problems in a loop here. Don't know if you can spot whats going on..
                                Have just included the important parts for brevity.

                                I have a nested ruby array of points curves. The points are coming from a getter-method-call in a Ruby-class. The @points can be of vary length.
                                The problem is that RARRAY(curve_rbPoints)->len always gives the same length, so the code fails..
                                Is it because I'm hoisting the variable ?
                                I just found this bug so havent tested much yet..

                                NOTE: I should mention it get's the correct length 1st time round.
                                edit: nope.

                                // VALUE curves = [ curve, curve, etc ] // @points = [point3d, point3d, etc]
                                	
                                	const VALUE get_points = rb_intern("get_points"); //getter method for @points
                                	int curves_size = RARRAY(curves)->len; 
                                	VALUE curve, curve_rbPoints;
                                	int rCrv_len, i;
                                	
                                	// Inside a loop 
                                	for (i = 0; i < curves_size; i++) {
                                		
                                		curve = rb_ary_entry(curves, i); //My class Ec-curve instance"
                                		curve_rbPoints = rb_funcall(curve, get_points, 0); //Gets @points in current curves[index]
                                		rCrv_len = RARRAY(curve_rbPoints)->len; //WRONG LENGTH! 
                                
                                //Nested for loop is coming based on rCrv_len length
                                
                                1 Reply Last reply Reply Quote 0
                                • T Offline
                                  tt_su
                                  last edited by 1 Sept 2014, 13:27

                                  @jolran said:

                                  I have a nested ruby array of points curves. The points are coming from a getter-method-call in a Ruby-class. The @points can be of vary length.
                                  The problem is that RARRAY(curve_rbPoints)->len always gives the same length, so the code fails..
                                  Is it because I'm hoisting the variable ?
                                  I just found this bug so havent tested much yet..

                                  NOTE: I should mention it get's the correct length 1st time round.
                                  edit: nope.

                                  That only works with older Ruby I think, 1.8.6 or earlier. After that they changed the data structure so you should use the RARRAY_LEN macro. That macro doesn't exist on early Ruby so I conditionally define it:

                                  #ifndef RARRAY_LEN
                                  #define RARRAY_LEN(x) (RARRAY(x)->len)
                                  #endif
                                  

                                  https://bitbucket.org/thomthom/tt-library-2/src/24f6daa97b4ed67836d67ad4ac2f2c2806ca2a6e/Ruby%20C%20Extensions/Bezier/TT_Geom_Bezier.c?at=Version%202.9#cl-14

                                  When you look up info on Ruby C Extension programming make sure you check the date of the source. And refer to a recent version of README.EXT.

                                  I also find a lot of clues in "Ruby MRI identifier search": http://rxr.whitequark.org/mri/ident

                                  1 Reply Last reply Reply Quote 0
                                  • J Offline
                                    jolran
                                    last edited by 1 Sept 2014, 13:46

                                    Ahhh. A solution perhaps ๐Ÿ˜„
                                    I'm running Sketchup 2013 in debug mode. So it should be running Ruby 1.8.6 though ?

                                    This has been a very annoying problem to solve. I'm clueless.

                                    There's no error but irratic behavior with wrong values which makes it hard to track.

                                    I was thinking it had something to do with me calling instance method from a class
                                    sort of thing. The "curve" is an instance from a class I created and not a Sketchup curve, but I assume you got that part.

                                    I suppose I could make the Ruby array an accessor and then use instance var get, but I rather not.

                                    Will try your code when I get to my workstation later.

                                    Thanks!

                                    1 Reply Last reply Reply Quote 0
                                    • T Offline
                                      tt_su
                                      last edited by 1 Sept 2014, 14:11

                                      I don't see anything immediately wrong. But have you checked and validated the input data?
                                      Feels like there's some issue not located to that small snippet you have. If a complex case fails, try to reproduce in a small standalone case.

                                      Btw, rb_intern returns ID, not VALUE. At least in Ruby 1.8 they are typedef of the same, but you cannot be sure of that and should make sure when a function use ID vs VALUE.

                                      1 Reply Last reply Reply Quote 0
                                      • T Offline
                                        tt_su
                                        last edited by 1 Sept 2014, 14:12

                                        Also, you're using out C++ example? Then you don't have to declare all variables in advance. That's very old C syntax. Even newer C syntax allow you to declare variables when you need them.

                                        1 Reply Last reply Reply Quote 0
                                        • J Offline
                                          jolran
                                          last edited by 1 Sept 2014, 16:18

                                          I am doing a C++ extension, yes.

                                          @unknownuser said:

                                          rb_intern returns ID, not VALUE

                                          ๐Ÿ˜ฎ Well that changes things. That could be it. Will test that in various combinations and report back.

                                          So would the syntaxrb_funcall(rb_intern("get_points")etc... be better then instead of storing it ?

                                          @unknownuser said:

                                          try to reproduce in a small standalone case.

                                          I have created a smallish testcase. Although I needed some classes for that.
                                          So the code become over 500 lines.
                                          I run that code in Alex ruby code editor while debug. Don't know if that can affect the scope of class or anything.

                                          And I have tested the data before sending in to c-extension, it's alright in Ruby.

                                          The C++ code may very well have logic errors I havent found yet. So I have to scan that through again. It looks like this is the main problem though, since I'm dependent of array length for next iterations. When all the arrays(curves) have same length code is working.

                                          @unknownuser said:

                                          That's very old C syntax. Even newer C syntax allow you to declare variables when you need them.

                                          I couldent tell whats proper syntax or not, yet. That does sound easier.
                                          Does that go for loops/iterators as well?

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

                                          Advertisement