$out ||= $stdout $dl_h = ARGV[0] || "dl.h" # import DLSTACK_SIZE, DLSTACK_ARGS and so on File.open($dl_h){|f| pre = "" f.each{|line| line.chop! if( line[-1] == ?\ ) line.chop! line.concat(" ") pre += line next end if( pre.size > 0 ) line = pre + line pre = "" end case line when /#define\s+DLSTACK_SIZE\s+\(?(\d+)\)?/ DLSTACK_SIZE = $1.to_i when /#define\s+DLSTACK_ARGS\s+(.+)/ DLSTACK_ARGS = $1.to_i when /#define\s+DLTYPE_([A-Z_]+)\s+\(?(\d+)\)?/ eval("#{$1} = #{$2}") when /#define\s+MAX_DLTYPE\s+\(?(\d+)\)?/ MAX_DLTYPE = $1.to_i when /#define\s+MAX_CALLBACK\s+\(?(\d+)\)?/ MAX_CALLBACK = $1.to_i end } } CDECL = "cdecl" STDCALL = "stdcall" CALLTYPES = [CDECL, STDCALL] DLTYPE = { VOID => { :name => 'void', :type => 'void', :conv => nil, }, CHAR => { :name => 'char', :type => 'char', :conv => 'NUM2CHR(%s)' }, SHORT => { :name => 'short', :type => 'short', :conv => 'NUM2INT(%s)', }, INT => { :name => 'int', :type => 'int', :conv => 'NUM2INT(%s)', }, LONG => { :name => 'long', :type => 'long', :conv => 'NUM2LONG(%s)', }, LONG_LONG => { :name => 'long_long', :type => 'LONG_LONG', :conv => 'NUM2LL(%s)', }, FLOAT => { :name => 'float', :type => 'float', :conv => 'RFLOAT(%s)->value', }, DOUBLE => { :name => 'double', :type => 'double', :conv => 'RFLOAT(%s)->value', }, VOIDP => { :name => 'ptr', :type => 'void *', :conv => 'NUM2PTR(%s)', }, } def func_name(ty, argc, n, calltype) "rb_dl_callback_#{DLTYPE[ty][:name]}_#{argc}_#{n}_#{calltype}" end $out << (< 0 ? ", args[#{argc}]" : ""}; #{ (0...argc).collect{|i| " args[%d] = LONG2NUM(stack%d);" % [i,i] }.join("\n") } cb = rb_ary_entry(rb_ary_entry(#{proc_entry}, #{ty}), #{(n * DLSTACK_SIZE) + argc}); ret = rb_funcall2(cb, cb_call, #{argc}, #{argc > 0 ? 'args' : 'NULL'}); return #{DLTYPE[ty][:conv] ? DLTYPE[ty][:conv] % "ret" : ""}; } EOS end end end end $out << (<