sketchucation logo sketchucation
    • Login
    ℹ️ Licensed Extensions | FredoBatch, ElevationProfile, FredoSketch, LayOps, MatSim and Pic2Shape will require license from Sept 1st More Info

    Weirdest loading bug ever?

    Scheduled Pinned Locked Moved Developers' Forum
    16 Posts 2 Posters 680 Views 2 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.
    • Dan RathbunD Offline
      Dan Rathbun
      last edited by

      There are a few quirks you need to be aware of with scrambled rubies.

      1) If your using the SketchupExtension class (see file Tools/extensions.rb,) the file refered to in the path attribute must be an unscrambled script. Convention is that it is named with a "_loader.rb" suffix. So if the name of your plugin is "widget" then the registration script in the plugins folder would be "lothcat_widget_ext.rb", which sets the path to "lothcat/widget/widget_loader.rb" (in your plugin subfolder, of your author subfolder, which you should be using, by the way.)
      The script for "lothcat/widget/widget_loader.rb" would be a one-liner, that simply says:
      Sketchup.require("lothcat/widget/widget")
      which will (if it isn't loaded,) will call Sketchup.load("lothcat/widget/widget.rbs")

      2) **Special Ruby vars**The special Ruby keywords (actually built-in functions,) __FILE__ and __LINE__ do NOT work inside scrambled rbs scripts (as of v8.0M1.) This is because scrambled scripts are loaded into the system as an encrypted String, decrypted by Sketchup.load() internally into a plain text String, and that String is then passed as the argument to the Object.eval() method. Google neglected to search and replace those two constants, before passing the code String to eval. I've reported it in the last beta round, and we've complained about it all thru the ver 7 lifecycle as well.
      Hoping it will be fixed in the next release.

      Workaround:

      Keep a reference to your SketchupExtension instance object, by doing this for your extension registration script (this file goes in the main Plugins folder.)
      lothcat_widget_ext.rb

      require('extensions.rb')
      
      module Lothcat  # Proprietary TopLevel Namespace; No Tresspassing!
      
        module Widget  # Namespace for THIS plugin
      
          # Create an entry in the Extension list that loads
          #  a script called; "lothcat/widget/widget_loader.rb"
        
      
          @@plugin = SketchupExtension.new( "Lothcat's Widget", "lothcat/widget/widget_loader.rb" )
          
          @@plugin.creator   = 'Lothcat'
          @@plugin.copyright = "(c)2011 by Lothcat"
          
          @@plugin.version   = '1.0.0'
      
          @@plugin.description = "A Widget that does fancy things."
          
          Sketchup.register_extension( @@plugin, true )
          
          unless @@plugin.class.method_defined?(;path)
            #
            # define a singleton method for @@plugin to access the path attribute
            # (because Google did not do it in extensions.rb !!)
            #
            def @@plugin.path()
              @path
            end
          end # unless
          
          # Create local path and filename constants;
          #
          PATH = @@plugin.path()
          LOADER_SUFFIX = '_loader'
          LOADER = File.basename(PATH)
          RBSFILE = LOADER.split("_")[0] << '.rbs'
      
          # RELDIR is relative to Plugins dir, OR the dir from
          # the $LOAD_PATH array that require used to find it.
          RELDIR = File.dirname(PATH)
          ABSDIR = File.expand_path(RELDIR) # absolute path
      
        end # module Lothcat;;Widget
        
      end # module Lothcat
      

      "lothcat/widget/widget_loader.rb"

      Sketchup.require("lothcat/widget/widget")
      

      Now all of the code in the "lothcat/widget/widget.rbs" file should also be namespace wrapped within module Lothcat::Widget like so:

      require('sketchup.rb')
      module Lothcat;;Widget
      
        # The constants PATH, ABSDIR, RELDIR, RBSFILE, etc., can be
        # accessed here because they are local to this namespace.
        # The same is true for the module var @@plugin, which is the
        # reference to your SketchupExtension plugin instance.
      
        # The rest of your scrambled code goes here.
        # Can have nested submodules and class definitions, etc.
      
        ### Do only once block
        #
        unless file_loaded?( RBSFILE )
      
          # define menu items and toolbars
      
          file_loaded( RBSFILE )
      
        end # once block
      
      end #mod Lothcat;;Widget
      

      I'm not here much anymore.

      1 Reply Last reply Reply Quote 0
      • L Offline
        lothcat
        last edited by

        I'm trying to use this loader, but I keep getting errors. Specifically:

        Error Loading File F:/Program Files (x86)/Google/Google SketchUp 7/Plugins/lothcat/widget/widget.rb
        uninitialized constant Lothcat::Widget::RBSFILEError Loading File F:/Program Files (x86)/Google/Google SketchUp 7/Plugins/lothcat/widget/widget_loader.rb
        uninitialized constant Lothcat::Widget::RBSFILEError Loading File lothcat_widget_ext.rb
        uninitialized constant Lothcat::Widget::RBSFILE

        When I changed the names, I still get an uninitialized constant error.

        1 Reply Last reply Reply Quote 0
        • Dan RathbunD Offline
          Dan Rathbun
          last edited by

          Are you loading the "lothcat/widget/widget.rb" directly using the load() command at the console?
          If so you need to first load "lothcat_widget_ext.rb" where the RBSFILE constant gets defined.

          You need to learn how to debug !! I cannot always do it for you.
          I inserted debugging puts() statements into the "lothcat_wigdet_ext.rb" file, like so:

              # Create local path and filename constants;
              #
              PATH = @@plugin.path()
              puts "Lothcat;;Widget;;PATH = '#{PATH}'"
              LOADER_SUFFIX = '_loader'
              LOADER = File.basename(PATH)
              puts "Lothcat;;Widget;;LOADER = '#{LOADER}'"
              RBSFILE = LOADER.split("_")[0] << '.rbs'
              puts "Lothcat;;Widget;;RBSFILE = '#{RBSFILE}'"
              
           
              # RELDIR is relative to Plugins dir, OR the dir from
              # the $LOAD_PATH array that require used to find it.
              RELDIR = File.dirname(PATH)
              puts "Lothcat;;Widget;;RELDIR = '#{RELDIR}'"
              ABSDIR = File.expand_path(RELDIR) # absolute path
              puts "Lothcat;;Widget;;ABSDIR = '#{ABSDIR}'"
          
          

          I then loaded the file, and the console output was:
          Lothcat::Widget::PATH = 'lothcat/widget/widget_loader.rb' Lothcat::Widget::LOADER = 'widget_loader.rb' Lothcat::Widget::RBSFILE = 'widget.rbs' Lothcat::Widget::RELDIR = 'lothcat/widget' Lothcat::Widget::ABSDIR = 'F:/Program Files (x86)/Google/Google SketchUp 7/Plugins/lothcat/widget'

          Looks to me like you are not loading loading the extension registration script, before the plugin script.

          I'm not here much anymore.

          1 Reply Last reply Reply Quote 0
          • Dan RathbunD Offline
            Dan Rathbun
            last edited by

            Also... the "lothcat/widget/widget_loader.rb" can be changed so it autoloads either an rb or an rbs file.
            This can make it easier during development.

            "lothcat/widget/widget_loader.rb"

            #
            #  "widget_loader.rb"
            #
            
            require('sketchup.rb')
             
            module Lothcat;;Widget  # Namespace for THIS plugin
             
                # Conditionally loads a script&#058;
                #  1) trys; "lothcat/widget/widget.rb"
                #  2) trys; "lothcat/widget/widget.rbs"
               
                begin
            
                  require(File.join(RELDIR,"widget.rb"))
            
                rescue LoadError ==> e
            
                  if e.message.include?("no such file to load -- #{RELDIR}/widget.rb")
                  
                    begin
                      Sketchup.require(File.join(RELDIR,"widget.rbs"))
                    rescue
                      raise
                    else
                      unless file_loaded?(File.join(RELDIR,File.basename(__FILE__)))
                        file_loaded(File.join(RELDIR,File.basename(__FILE__)))
                      end # if not loaded
                    end
                  
                  else
                    raise  # just reraise the error
                  end
            
                else
            
                  unless file_loaded?(File.join(RELDIR,File.basename(__FILE__)))
                    file_loaded(File.join(RELDIR,File.basename(__FILE__)))
                  end # if not loaded
            
                end
             
            end # module Lothcat;;Widget
            
            

            I'm not here much anymore.

            1 Reply Last reply Reply Quote 0
            • L Offline
              lothcat
              last edited by

              You're right, I'm leaning on you a lot - it's because you're introducing a ton of stuff here that I've never used, and I wasn't even sure where to begin debugging. I'm still new to this.

              I tried modifying your code to my module, but when it didn't work, I tried making the snippets exactly how you wrote them.

              I'm putting the ext file in the plugin folder, and the others under lothcat/widget, then starting up sketchup rather than using load. The error is what appears on startup. I thought maybe it was loading the files in the @@plugin statement, so I moved that further down... and that didn't work either.

              I can fiddle with it on my own for a while to try to find the problem.

              Thank you so much for your help!

              1 Reply Last reply Reply Quote 0
              • Dan RathbunD Offline
                Dan Rathbun
                last edited by

                Why are you still using Sketchup 7 ??

                Version 8 fixes all manner of bugs, and runs Ruby v1.8.6-p287
                SU 7, "out-of-the-box" still has Ruby v1.8.0 (initial rel.)

                If you don't want to move up to ver 8, at the very least, update the Ruby DLL in the "Sketchup 7" dir, to v1.8.6-p287.

                Get it here: Ruby Interpreter DLLs (Win32)

                I'm not here much anymore.

                1 Reply Last reply Reply Quote 0
                • L Offline
                  lothcat
                  last edited by

                  I'm still using seven because I want to make sure that everyone in the company can use it, but if I have to force people to upgrade, so be it.

                  Turning off the RELDIR/ABSDIR calls seems to fix it for now.

                  1 Reply Last reply Reply Quote 0
                  • Dan RathbunD Offline
                    Dan Rathbun
                    last edited by

                    @lothcat said:

                    I'm still using seven because I want to make sure that everyone in the company can use it, but if I have to force people to upgrade, so be it.

                    Well OK.. but update the DLL to v1.8.6-p287, at least. Then retry the code.

                    @lothcat said:

                    Turning off the RELDIR/ABSDIR calls seems to fix it for now.

                    That does not make sense.. and is not a real solution.

                    When you get an error during Sketchup startup.. the display of the error messages are hard to read in that little box. Press the OK button, and let Sketchup finish loading.

                    Immediately open the Ruby Console.
                    and type $!
                    (The last error message will be redisplayed.)
                    ... then immediately, type puts $@
                    (The backtrace for that last error will be displayed.)

                    Don't make any typo errors in the console, or those two variables will lose the info from the LoadError, and take on new typo booboo error!

                    The backtrace will list the error and the filename where the error occured, followed by a colon, and the line number from the code.
                    Then the same for the file and line that called the previous line, and so on, all the way back to the original require() call, that tried to load "lothcat_widget_ext.rb"

                    So it's the first line of the backtrace where the actual error occurs. The backtrace you sent earlier shows that some of those constants may not be getting set.

                    I will bet that it's because your running Ruby v1.8.0, update that DLL.

                    Debugging tip. Always verify that the first file to load, is correct. So debug the extension registration script, and all those constant will be available in the plugin file.

                    I'm not here much anymore.

                    1 Reply Last reply Reply Quote 0
                    • Dan RathbunD Offline
                      Dan Rathbun
                      last edited by

                      Ok found it!!!

                      Duh (slap me.) File.expand_path assumes the relative path is from the current working directory.
                      Which you can get:
                      Dir.getwd

                      So in the example above:
                      (line 42) ABSDIR = File.expand_path(RELDIR) # absolute path
                      will be wrong.

                      I'm doing this in my files now:

                          ROOT = $LOAD_PATH.find(false) do |abspath|
                            Kernel.test(?d, File.join(abspath,RELDIR) )
                          end
                          if ROOT
                            ABSDIR = File.join( ROOT, RELDIR )
                          else
                            # assume the target dir is directly below, the dir that THIS file is in.
                            ABSDIR = File.join( File.dirname(__FILE__), RELDIR )
                          end
                      
                      

                      I'm not here much anymore.

                      1 Reply Last reply Reply Quote 0
                      • L Offline
                        lothcat
                        last edited by

                        Thank you so much! It's working now and I'm not having that weird loading bug!

                        Also, thank you for being patient with me. This was a real learning experience.

                        1 Reply Last reply Reply Quote 0
                        • Dan RathbunD Offline
                          Dan Rathbun
                          last edited by

                          @lothcat said:

                          Thank you so much! It's working now and I'm not having that weird loading bug!

                          Excellent!

                          @lothcat said:

                          Also, thank you for being patient with me. This was a real learning experience.

                          I would be very worried if you had not learned anything, here .... 😆

                          I'm not here much anymore.

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

                          Advertisement