#----------------------------- # olegen.rb # $Revision$ #----------------------------- require 'win32ole' class WIN32COMGen def initialize(typelib) @typelib = typelib @receiver = "" end attr_reader :typelib def ole_classes(typelib) begin @ole = WIN32OLE.new(typelib) [@ole.ole_obj_help] rescue WIN32OLE_TYPE.ole_classes(typelib) end end def generate_args(method) args = [] if method.size_opt_params >= 0 size_required_params = method.size_params - method.size_opt_params else size_required_params = method.size_params - 1 end size_required_params.times do |i| if method.params[i] && method.params[i].optional? args.push "arg#{i}=nil" else args.push "arg#{i}" end end if method.size_opt_params >= 0 method.size_opt_params.times do |i| args.push "arg#{i + size_required_params}=nil" end else args.push "*arg" end args.join(", ") end def generate_argtype(typedetails) ts = '' typedetails.each do |t| case t when 'CARRAY', 'VOID', 'UINT', 'RESULT', 'DECIMAL', 'I8', 'UI8' # raise "Sorry type\"" + t + "\" not supported" ts << "\"??? NOT SUPPORTED TYPE:`#{t}'\"" when 'USERDEFINED', 'Unknown Type 9' ts << 'VT_DISPATCH' break; when 'SAFEARRAY' ts << 'VT_ARRAY|' when 'PTR' ts << 'VT_BYREF|' when 'INT' ts << 'VT_I4' else if String === t ts << 'VT_' + t end end end if ts.empty? ts = 'VT_VARIANT' elsif ts[-1] == ?| ts += 'VT_VARIANT' end ts end def generate_argtypes(method, proptypes) types = method.params.collect{|param| generate_argtype(param.ole_type_detail) }.join(", ") if proptypes types += ", " if types.size > 0 types += generate_argtype(proptypes) end types end def generate_method_body(method, disptype, types=nil) " ret = #{@receiver}#{disptype}(#{method.dispid}, [" + generate_args(method).gsub("=nil", "") + "], [" + generate_argtypes(method, types) + "])\n" + " @lastargs = WIN32OLE::ARGV\n" + " ret" end def generate_method_help(method, type = nil) str = " # " if type str += type else str += method.return_type end str += " #{method.name}" if method.event? str += " EVENT" str += " in #{method.event_interface}" end if method.helpstring && method.helpstring != "" str += "\n # " str += method.helpstring end args_help = generate_method_args_help(method) if args_help str += "\n" str += args_help end str end def generate_method_args_help(method) args = [] method.params.each_with_index {|param, i| h = " # #{param.ole_type} arg#{i} --- #{param.name}" inout = [] inout.push "IN" if param.input? inout.push "OUT" if param.output? h += " [#{inout.join('/')}]" h += " ( = #{param.default})" if param.default args.push h } if args.size > 0 args.join("\n") else nil end end def generate_method(method, disptype, io = STDOUT, types = nil) io.puts "\n" io.puts generate_method_help(method) if method.invoke_kind == 'PROPERTYPUT' io.print " def #{method.name}=(" else io.print " def #{method.name}(" end io.print generate_args(method) io.puts ")" io.puts generate_method_body(method, disptype, types) io.puts " end" end def generate_propputref_methods(klass, io = STDOUT) klass.ole_methods.select {|method| method.invoke_kind == 'PROPERTYPUTREF' && method.visible? }.each do |method| generate_method(method, io) end end def generate_properties_with_args(klass, io = STDOUT) klass.ole_methods.select {|method| method.invoke_kind == 'PROPERTYGET' && method.visible? && method.size_params > 0 }.each do |method| types = method.return_type_detail io.puts "\n" io.puts generate_method_help(method, types[0]) io.puts " def #{method.name}" if klass.ole_type == "Class" io.print " OLEProperty.new(@dispatch, #{method.dispid}, [" else io.print " OLEProperty.new(self, #{method.dispid}, [" end io.print generate_argtypes(method, nil) io.print "], [" io.print generate_argtypes(method, types) io.puts "])" io.puts " end" end end def generate_propput_methods(klass, io = STDOUT) klass.ole_methods.select {|method| method.invoke_kind == 'PROPERTYPUT' && method.visible? && method.size_params == 1 }.each do |method| ms = klass.ole_methods.select {|m| m.invoke_kind == 'PROPERTYGET' && m.dispid == method.dispid } types = [] if ms.size == 1 types = ms[0].return_type_detail end generate_method(method, '_setproperty', io, types) end end def generate_propget_methods(klass, io = STDOUT) klass.ole_methods.select {|method| method.invoke_kind == 'PROPERTYGET' && method.visible? && method.size_params == 0 }.each do |method| generate_method(method, '_getproperty', io) end end def generate_func_methods(klass, io = STDOUT) klass.ole_methods.select {|method| method.invoke_kind == "FUNC" && method.visible? }.each do |method| generate_method(method, '_invoke', io) end end def generate_methods(klass, io = STDOUT) generate_propget_methods(klass, io) generate_propput_methods(klass, io) generate_properties_with_args(klass, io) generate_func_methods(klass, io) # generate_propputref_methods(klass, io) end def generate_constants(klass, io = STDOUT) klass.variables.select {|v| v.visible? && v.variable_kind == 'CONSTANT' }.each do |v| io.print " " io.print v.name.sub(/^./){$&.upcase} io.print " = " io.puts v.value end end def class_name(klass) klass_name = klass.name if klass.ole_type == "Class" && klass.guid && klass.progid klass_name = klass.progid.gsub(/\./, '_') end if /^[A-Z]/ !~ klass_name || Module.constants.include?(klass_name) klass_name = 'OLE' + klass_name end klass_name end def define_initialize(klass) <