The libfile comes out as SUEX_HelloWorld.so and is loaded by
require 'SUEX_HelloWorld'
This setup forces the name of the .so to be SUEX_HelloWorld.so.
I would like a setup that allows me to rename the .so file after export. Is that possible?
First of all, why would you like to rename the file?
Secondly, the file extension is defined by Ruby, not by SketchUp. On macOS, these files have a .bundle extension.
I assume you’re working with Windows, and if you look thru the Tools/RubyStdLib/platform_specific folder in the SU install, you’ll see several files with the .so extension.
When you require a file, Ruby checks for files with a matching name and either the .rb or .so extension.
You could use a different extension and load the with Fiddle, I’m not sure why one would want to do that. I’ve also never tried it.
I think that you are wanting to rename the filename (and not the .so filetype) as suggested.
With Ruby’s .so files, the entry point function must have the same name as the file with an “Init_” prefix, otherwise Ruby would not know what the entry point function name was.
More Info: It is Ruby’s Kernel#require global method that enforces the file basename ↔ "Init_#{basename}" entry point function limitation. As Greg points out below, there are other means of loading a library into Ruby that are not limited in this way.
So, speaking about the SketchUp team’s example, they first likely decided what they wanted the .so filename to be, and then made sure to give the entry point function the same name, prefixed with “Init_”. (If the name differed, Ruby would throw an exception with a message like “entry point not found” or similar.)
Usually the entry point function serves to define the library’s Ruby objects (module, classes and methods.)
For in depth on how to write C Ruby extensions, see:
Yes, a programmer could write a normal DLL and export functions normally, or use a normal 3rd party DLL that exports functions for general use and load that library into Ruby using Fiddle and access it’s functions using Fiddle::Importer.
Sorry, maybe not enough coffee when I wrote the above. SUEX_HelloWorld.so is the file name, the basename is SUEX_HelloWorld. That can be anything you want. What classes/functions are defined in the file do not have any relationship to the file name in Ruby. The tools you use to compile the file may have naming conventions (like MSVS), but Ruby does not.
Importer is for when one wants to use functions in Fiddle. I was referring to using the LoadLibraryW function from Kernel32 to load the file. An example would be code in the mysql2 gem.
Oh yes, of course. It slipped my mind so I added the following correction to my post above:
More Info: It is Ruby’s Kernel#require global method that enforces the file basename ↔ "Init_#{basename}" entry point function limitation. As Greg points out below, there are other means of loading a library into Ruby that are not limited in this way.
It’s been quite a while since I created my own *.so file. After looking into this some more, Ruby’s convention as to basenames is to use lowercase, with underscores for ‘word’ separators.
So, openssl.so file has an entry point of Init_openssl. Another example would be puma_http11.so with an entry point of Init_puma_http11.
The uppercase names used in Ruby code are assigned by the rb_define_module & rb_define_class functions.
The reason for a rename is that Ruby locks the .so file on load which prevents the user from updating the extension from within Sketchup. The solution to this is to copy the .so file on startup and then load the copy. This copy can be in another directory with the same name but I would prefer to have the copy in the same directory as the original with a new name. The problem is this:
I haven’t checked anything like that for quite a while. Encoding has been an issue with Windows Ruby in the past, many of the problems are fixed in more recent versions.
Re reloading *.so files, that has always been problematic in stand-alone Ruby. Many gems (some which may involve reloading code) have gone to the trouble of writing limited parsers for yaml or json so the std-lib extensions did not need to be loaded.
Okay, so compile your .so as the normal working name like "my_lib.so" (with the entry point function named "Init_my_lib",) then manually rename it to "my_lib_deploy.so" (or some similar differentiation) in the plugin package.
Then at runtime, use FileUtils::copy_file to make a copy with the proper "my_lib.so" name and require it normally.
Whenever the extension is updated, it will be the deployment file that will get overwritten, not the runtime file. Somehow the update process should inform the user that SketchUp needs to be restarted.