From: Park Heesob Date: 2006-04-27T00:11:17+09:00 Subject: How to make compiler independent extension library on Windows? Hello, I know there are some issues with various compiler versions of ruby distribution and extension library. Mainly VC++6.0 and VC++7.1 conflict. I guess many people have VC++7.1 and want to make extension library with VC++7.1. The library built with VC++6.0 is not working on the VC++7.1 compiled ruby distribution and vice versa. Here is the method to make compiler independent extension library. Because it is a draft version, some modifications might be needed. 1. Remove compile time dependency on ruby dll(msvcr71-ruby18.dll, msvcrt-ruby18.dll or others) 1-1. If not exist ruby_ext.h, make ruby_ext.h with make_header.rb ruby make_header.rb 1-2. Insert #include "ruby_ext.h" after the line #include "ruby.h" in the library source. #include "ruby.h" #include "ruby_ext.h" 1-3. Insert get_ruby_function(); at the first place of Init_xxx function in the library source. void Init_changejournal() { VALUE mWin32, cChangeJournal; get_ruby_function(); 2. Remove run time dependency on msvcrt dll (msvcrt.dll,msvcr71.dll or others) - Optional 2-1. Insert $CFLAGS.sub!("-MD","-MT") befre create_makefile in the extconf.rb $CFLAGS.sub!("-MD","-MT") create_makefile("win32/changejournal") 3. Make extension library as usual ruby extconf.rb nmake install Regards, Park Heesob =====file make_header.rb require 'rbconfig' File.open(Config::CONFIG['archdir']+'/ruby_ext.h',"w") {|f| func_arr = [] var_arr = [] File.read(Config::CONFIG['archdir']+'/ruby.h').each {|l| if l =~ /(^.*[\s|\*])(rb_\w*)(\s.+;$)/ f.puts "typedef #$1 (*p_#$2)#$3"; func_arr.push($2); elsif l =~ /RUBY_EXTERN VALUE (rb_[c|e]\w*);/ var_arr.push($1) end } File.read(Config::CONFIG['archdir']+'/intern.h').each {|l| if l =~ /(^.*\s)(rb_\w*)(\s.+;$)/ f.puts "typedef #$1 (*p_#$2)#$3"; func_arr.push($2); end } func_arr.each {|fn| f.puts "#undef #{fn}" f.puts "p_#{fn} r_#{fn};" f.puts "#define #{fn} r_#{fn}\n" } var_arr.each {|var| f.puts "#undef #{var}" f.puts "VALUE r_#{var};" f.puts "#define #{var} r_#{var}\n" } f.puts < #include HMODULE hinstLib; char* get_ruby_dll( void ) { static char psBuffer[128]; FILE *pPipe; if( (pPipe = _popen("ruby -r rbconfig -e \\"puts Config::CONFIG['RUBY_SO_NAME']+'.dll'\\"", "rt" )) == NULL ) return NULL; fgets(psBuffer, 128, pPipe); _pclose( pPipe ); if(*psBuffer) psBuffer[strlen(psBuffer)-1]=0; return psBuffer; } void get_ruby_function() { hinstLib = LoadLibrary(get_ruby_dll()); if (hinstLib == NULL) { exit(1); } DOC func_arr.each {|fn| f.puts "#{fn} = (p_#{fn})GetProcAddress(hinstLib, \"#{fn}\");" } var_arr.each {|var| f.puts "#{var} = *(VALUE*)GetProcAddress(hinstLib, \"#{var}\");" } f.puts "}" }