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

    DLL callback to ruby

    Scheduled Pinned Locked Moved Developers' Forum
    41 Posts 4 Posters 10.5k Views 4 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

      @alienizer said:

      oh ok, I get it. So in my loader, I can simply have it load the dll which will do all of what the rb does, and remove the rb alltogether?

      Well.. yes. That's what all the Ruby extended libraries do. They are compiled .so (shared object) files that create the Ruby classes and all their methods, that Ruby scripters use.

      However.. the loader is actually the require() method, and the library is loaded on demand when it's needed.

      I'm not here much anymore.

      1 Reply Last reply Reply Quote 0
      • A Offline
        Alienizer
        last edited by

        I see. So if I use require "test.so" in my loader, then I bypass win32api and it can be cross-platform? Can the dll do everything the rb can do? How do you get the Sketchup:: object in the dll? I suppose I need sketchup.h or something?

        I'm from Mars and moved to Earth to alienize you. Unfortunately, I became humanized.

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

          @alienizer said:

          I see. So if I use require "test.so" in my loader, then I bypass win32api and it can be cross-platform?

          Yes.. because an edition of Ruby is compiled for the platform it will run on (or even compiled on the user's platform itself.)
          There is a standard platform subdir, beneath the Ruby lib dir, whose name is equal to the Ruby constant RUBY_PLATFORM.
          On each platform, the Ruby require() method's C-side code, will use a platform specific API call to load shared library files (.so,.o,.dll,.dylib,...)
          So on Windows, require() is likely to be calling LoadLibrary from the kernel32.dll library. On another platform such as OSX, the name of the Lib file, and the load function may differ, but in the Ruby C source, conditional defines will take care of all that.

          So your code would also need to be compiled on both platforms. I don't have a Mac, but I imagine a few tweaks may be necessary, such as conditional defines, etc.

          @alienizer said:

          Can the dll do everything the rb can do?

          I would expect so. You must realize the Ruby is written in C, and creates C objects.
          A Ruby script is just an invention for human readability and productivity.
          The Ruby interpreter DLL (msvcrt-ruby18.dll) reads and converts the script-type definition blocks (for modules, classes and methods,) into C calls using the functions that begin with "rb_"

          @alienizer said:

          How do you get the Sketchup:: object in the dll? I suppose I need sketchup.h or something?

          The Sketchup object is a Ruby module, and you can call any of it's module methods from the C-side using rb_eval_string

          //C
            int_ver_major = NUM2INT( rb_eval_string("Sketchup.version.to_i") );
          

          However if you wish to use rb_funcall, you create a C-side identifier for it at the top of your code, and then in the Init_dllname function, you "init" it using rb_define_module("Sketchup"), like so:

          //C
          
          VALUE modSketchup;
          
          // Entry point for Ruby require() method;
          void Init_ExactcaseFilenameofDLL()
          {
            modSketchup = rb_define_module("Sketchup");
          }
          

          Since the module already exists, it's not re-created, your just making a handle to it. (The Sketchup Ruby API objects are created in a similar way, but are part of the sketchup.exe. When Sketchup loads, the last 3 things it does is, load the Ruby interpreter DLL, define the Ruby API objects, and process the Plugins & Tools folders.)

          I'm not here much anymore.

          1 Reply Last reply Reply Quote 0
          • A Offline
            Alienizer
            last edited by

            aaaaaaaaaaah OK, now it's clear to me. I can see exactly what you mean and how this works.

            Dan, thank you so much for your time to explain all this to me. I don't know how to thank you enough, and I wish I could return the favor, but you are obviously way above me that there is nothing you can learn from me. I realy appreciate it Dan.

            Now I'm gonna go play.........

            I'm from Mars and moved to Earth to alienize you. Unfortunately, I became humanized.

            1 Reply Last reply Reply Quote 0
            • A Offline
              Alienizer
              last edited by

              Dan, one last question, can the dll be compiled in 64bit or does it have to be 32bit like SK?

              Does the handle return by rb_define_module('Sketchup') correspond to the ISkpApplication interface?

              I'm from Mars and moved to Earth to alienize you. Unfortunately, I became humanized.

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

                @alienizer said:

                Dan, one last question, can the dll be compiled in 64bit or does it have to be 32bit like SK?

                I would say 32bit, because the Ruby that Sketchup loads is also 32bit. There is a 64bit Ruby edition, but it may be in the 1.9.x branch, which Sketchup cannot load even 1.9.x 32bit.

                @alienizer said:

                Does the handle return by rb_define_module('Sketchup') correspond to the ISkpApplication interface?

                I would say "not exactly". There may be some C++ methods from that interface, that are "Ruby wrapped" into the Sketchup module, as well as others from different C++ objects.

                Getting a handle on the application object (and from there it's window object, and then it's UI element objects, and so on...) are methods that the current Ruby Sketchup module lacks. You'll have to use a C++ call, as shown in the SDK examples to get the app handle.

                I'm not here much anymore.

                1 Reply Last reply Reply Quote 0
                • A Offline
                  Alienizer
                  last edited by

                  Thank Dan. So far, everything works great, I even got this to work...

                  modUI = rb_define_module('UI');
                  menu = rb_funcall(modUI, rb_intern('menu'), 0, nil);

                  but I'm stuck on this one...

                  rb_funcall(menu, rb_intern('add_item'), 1, rb_str_new2('File/Testing'));

                  It tells me "tried to create Proc object without a block"

                  Where do you learn all this? I can't find any docs on rb_intern or what to pass to it. I only guess!

                  I'm from Mars and moved to Earth to alienize you. Unfortunately, I became humanized.

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

                    The API add_item method takes 2 args, a String and a Block, ... not 1 arg.

                    I'm not here much anymore.

                    1 Reply Last reply Reply Quote 0
                    • A Offline
                      Alienizer
                      last edited by

                      @dan rathbun said:

                      The API add_item method takes 2 args, a String and a Block, ... not 1 arg.

                      Indeed! I figured it out, and the rb_intern('menu') takes one, a str of the submenu name, like "Plugins" right?

                      When I do rb_intern('add_submenu') with 1 arg of str "Testing", it adds only "T" to the Pluigns menu, the first letter only!?

                      If I don't use rb_str_new2 SK crash, Am I doing it right?

                      For the Block, do I have to use rb_something to pass the Block, or just the reference pointer?

                      Sorry to be a pain in the......

                      I'm from Mars and moved to Earth to alienize you. Unfortunately, I became humanized.

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

                        @alienizer said:

                        I can't find any docs on rb_intern or what to pass to it.

                        At the bottom of the "Extending Ruby" chapter, of the "Pick-Axe" book:
                        @unknownuser said:

                        *ID rb_intern(char name")

                        Returns an ID for a given name. If the name does not exist, a symbol table entry will be created for it.

                        I just pasted an example that used the rb_intern to create an ID... not sure if it's really needed. You can try just passing a normal string, as the method name argument.
                        (Using rb_intern on the C-side, is the same as using a Symbol on the Ruby side, thus:
                        :test_item or "test_item".intern or "test_item".to_sym

                        What are the arguments, for ruby C-side functions, generally?

                        The list at the bottom of the "Extending Ruby" chapter, is not complete, AND that edition was written for Ruby circa 1.6.x (so it's out of date.)

                        For a definitive list, refer to to the function prototypes, in the Ruby C source folder:
                        %(#000000)[**.../include/ruby-*<version>*/ruby/ruby.h**]
                        .. so if your using Ruby ver 1.8.6, the path would be:
                        %(#000000)[**.../include/ruby-1.8.6/ruby/ruby.h**]

                        ADD: .. and other header files as well.

                        I'm not here much anymore.

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

                          Yea, you need to use rb_str_new2 to convert the Cstring to a Ruby String.

                          I'm not here much anymore.

                          1 Reply Last reply Reply Quote 0
                          • A Offline
                            Alienizer
                            last edited by

                            Thanks Dan

                            I'm from Mars and moved to Earth to alienize you. Unfortunately, I became humanized.

                            1 Reply Last reply Reply Quote 0
                            • A Offline
                              Alienizer
                              last edited by

                              Dan, what is the Block expected in rb_funcall(menu, rb_intern('add_submenu')...

                              I keep getting the error "tried to create Proc object without a block" if I use 1 arg.

                              If I use 2 arg, I get "wrong number of arguments (2 for 1)" but even you said it needs 2!? Confusing 😕

                              I'm from Mars and moved to Earth to alienize you. Unfortunately, I became humanized.

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

                                @alienizer said:

                                For the Block, do I have to use rb_something to pass the Block, or just the reference pointer?

                                Not sure... the proc and block functions are listed in intern.h

                                Depends on if the block / proc will be defined at runtime on the Ruby side, or before hand in your C code.

                                This generated doxygen website is old (v 1.8.4) but you may find it easier to find things:
                                http://www.ruby-doc.org/doxygen/current/globals.html#index_r

                                I'm not here much anymore.

                                1 Reply Last reply Reply Quote 0
                                • A Offline
                                  Alienizer
                                  last edited by

                                  Thanks Dan

                                  I'm from Mars and moved to Earth to alienize you. Unfortunately, I became humanized.

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

                                    @alienizer said:

                                    Thanks Dan

                                    no problemo ...

                                    Also, if you have the Ruby Reference CHM, when you wish to see the C-side source for a method, you can click within the method's definition area, and a source box will unfold.

                                    I'm not here much anymore.

                                    1 Reply Last reply Reply Quote 0
                                    • A Offline
                                      Alienizer
                                      last edited by

                                      Sweet! But only ruby18-core.chm works out of the 3! Or is it me?

                                      I just posted http://forums.sketchucation.com/viewtopic.php?f=180&t=39119 another challange for you 😒 😳

                                      I'm from Mars and moved to Earth to alienize you. Unfortunately, I became humanized.

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

                                        @alienizer said:

                                        Sweet! But only ruby18-core.chm works out of the 3! Or is it me?

                                        ruby18.chm is a wrapper that loads both of the other two, as expandable nodes in the tree control.
                                        CHM files use a MSIE stub named hh.exe
                                        They a compiled HTML Help Markup files.
                                        You can get the HTML Help Workshop app on MS Download.

                                        I'm not here much anymore.

                                        1 Reply Last reply Reply Quote 0
                                        • A Offline
                                          Alienizer
                                          last edited by

                                          Yes indeed, I didn't know the other 2 were loaded into the one. That's a nice ref book! Thanks Dan.

                                          I'm from Mars and moved to Earth to alienize you. Unfortunately, I became humanized.

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

                                            @alienizer said:

                                            Yes indeed, I didn't know the other 2 were loaded into the one. That's a nice ref book! Thanks Dan.

                                            Well it's supplied with the mingGW compiled Windows Ruby one-click install packages. So I'm not responsible.

                                            Check your Private Messages

                                            I'm not here much anymore.

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

                                            Advertisement