[Tutorial] SketchUp Ruby C Extension
-
Hey guys,
So, I got the ruby extension process to work, but I seem to be running into one little catch... multithreading.
FYI: I'm using Pelle's C with the options TBD suggested in his SUExt example. I'm on a Win 7 (64 bit) system (though hopefully that won't matter).
I'm trying to use _beginthread, but using TBD's settings, it seems I have an unresolved symbol '_beginthread'.
Just to let you know, I am kind of new to multithreading and DLLs. I have created threaded applications, but never a threaded dll.
Taking an example program that I have gotten to compile and run as a standalone app (pelle's C option multithreaded (lib)), I add the libs, includes and functions required to make it a ruby extension and it suddenly can't resolve _beginthread.
A couple of modifications to TBD's project settings and I get it to compile and even be recognized by the irb. However, it seems the second the thread tries to run, the whole irb closes.
The settings I modified to "get it to work" was:
Runtime library from multithread (dll) to multithread (lib)
and turn off "Omit default library in object files"Any ideas?
Thanks,
Reg// general Windows #pragma comment(lib, "kernel32.lib") #pragma comment(lib, "gdi32.lib") #pragma comment(lib, "user32.lib") #pragma comment(lib, "shell32.lib") #pragma comment(lib, "advapi32.lib") // Ruby #define HAVE_ISINF 1 // isinf macro redefinition workaround #pragma comment(lib, "msvcrt-ruby18.lib"); // DLL #pragma comment(lib, "crt.lib"); #include <stdio.h> #include <windows.h> #include <process.h> // needed for _beginthread() // Ruby headers #include "ruby.h" void silly( void * ); // function prototype // De fining a space for information and references about the module to be stored internally VALUE KMRH = Qnil; int j = -1; // our function VALUE method_display_model(VALUE self, VALUE input) { // Our program's first thread starts in the main function. printf( "Now in the main function.\n" ); // Let's now create our second thread and ask it to start // in the silly() function. // _beginthread( silly, 0, (void*)12 ); //Commented out to see if the program would stay alive and it does // From here on there are two separate threads executing // our one program. // This main thread can call the silly() function if it wants to. while(j != 0) { silly( (void*)j ); j--; } Sleep( 10000 ); int i = NUM2INT(input); return INT2NUM(i + 1); } // The initialization method for this module void Init_KMRH(void) { KMRH = rb_define_class("KMRH", rb_cObject); rb_define_method(KMRH, "display", method_display_model, 1); } void silly( void *arg ) { int k = 10; while(k-- != 0) { // printf( "The silly() function was passed %d\n", (INT_PTR)arg ); printf( "The silly() function was passed %d\n", k ); } }
-
That's way beyond me. I've not dealt with threading at all. But I'll be keeping an eye on this as it something I might want to do in the future.
-
So, I have to apologize for wasting your time...
First thing I need to do (yet again) is RTFM.
The answer to threading is incredibly simple:
_beginthread( silly, 0, (void*)12 );becomes
rb_thread_create( silly, (void*)12);
found it on:
http://ruby-doc.org/docs/ProgrammingRuby/html/ext_ruby.htmlSo, if you will excuse me, I need to go beat myself half to death...
-
You will not get any joy from using Ruby threads. They are "green" threads. It's just Ruby dividing up the tasks itself - not the system. So making a thread in Ruby will not prevent SU from freezing.
-
And Daniel Berger's win32-thread package that wraps native threads is still Alpha and unstable (AFAIK.)
-
I'm on to the next challenge now... building for the 1.8.7-p334 version my colleagues prefer (better compatibility with certain gems). Unfortunately this one was built with with mingw, and my VS2010 build flow that worked for 1.8.6-p287 (mswin) is not successful here. I have the following results:
- build against 1.8.7-p334 built from source with VS2010: compile succeeds, load fails with missing dll msvcrt-ruby18-vc100 (or something like that). If I supply the dll, Sketchup crashes.
- build against 1.8.7-p334 one-click install (mingw): compile fails. Lots of warnings about win32.h and missing ruby API functions
- hybrid build pointing includes to mswin build of 1.8.7-p334, library from mingw one-click: link error
I'm under the impression that because dll's use the C API it should be possible to load a VS2010-generated extension into a mingw-built Ruby. Is it a hopeless cause?
Thanks,
Jeff -
Today I made a startling discovery: the plugin I built under VS2010 against the 1.8.6-p287 mswin Ruby will load and run without changes in the 1.8.7-p334 mingw build. So the Ruby version and compiler both mismatch, and yet everything works. I'm dumbfounded but delighted, and my previous question is now moot.
-
-
@thomthom said:
Btw, does anyone know how one can make extconf.rb and make/nmake output their files to a given folder? I'd like to make it so that each platform outputs its generated files to separate directories.
Anyone know how to achieve this?
Making it so that when I build and compile under Windows everything is placed in a "win32" folder and "osx" when using OSX?
Or rather, to clarify, I know how to do conditionals - just don't know how to control where the generated files are output. -
and you are compiling from the commandline, not from within the Visual Studio GUI interface, correct ?
-
Currently using
nmake
that comes with MS VS C++.And I'm using a
extconf.rb
withmkfm
to generate the makefile. -
Is it possible to build an Ruby C Extension under Windows that doesn't require additional libraries? When using Visual C++ to build the extensions require the C++ runtime library.
-
yes. my old example did that. best is to check the DLL imports section to see what functions it requires
-
@unknownuser said:
yes. my old example did that. best is to check the DLL imports section to see what functions it requires
Ah, the Pelles C project! Is it possible to use to to just compile the C source without creating a project? (just trying to find a solution without creating too many extra project files.) -
@unknownuser said:
Is it possible to use to to just compile the C source without creating a project? (just trying to find a solution without creating too many extra project files
the .ppj file is just a collection of commands. you can easily convert it to a .bat file if you dont want to have extra files (remember to create the .def file for the .dll link)
-
Do you remember the cause of the
C:\ruby\src\ruby-1.8.6-p111\missing.h(71): error #1050: Redefinition of macro 'isinf'.
error? And can you explain what your workaround actually do?Trying to set up a project myself so I actually understand this.
-
And why is the macro redefinition just a warning for this guy, but an error in Pelles C?
https://github.com/barrie0482/rrdruby_win32_build/wiki -
hm... there is an
msvcrt-ruby18.dll
in the SketchUp folder - can I make my Visual Studio C++ project rely on this instead? So when the C Extension loads under SketchUp Ruby the runtime is there - installed by SketchUp. ?? -
@unknownuser said:
@unknownuser said:
And can you explain what your workaround actually do?
isinf is already defined in PellesC libraries so there is no need to include that file again.
But I am not including it myself - it's an error that comes from the Ruby missing.h file... :S
Building hello_world.obj. Use <stdlib.h> instead of non-standard <malloc.h> C;\ruby\src\ruby-1.8.6-p111\missing.h(71); error #1050; Redefinition of macro 'isinf'. *** Error code; 1 *** Done.
-
@unknownuser said:
http://msdn.microsoft.com/en-us/library/windows/desktop/ms682586(v=vs.85).aspx - the DLL is already loaded by Sketchup so it will use that version.
When compiling with Pelles C, right? Any way to make VC++'s nmake rely on the bundled SketchUp CRT instead of the VSC++ CRT? (splitting my quest into two projects here...)
Advertisement