Module DL::Importable::Internal
In: dl/lib/dl/struct.rb
dl/lib/dl/import.rb

Methods

Classes and Modules

Class DL::Importable::Internal::Memory
Class DL::Importable::Internal::Struct
Class DL::Importable::Internal::Union

Public Instance methods

[Source]

# File dl/lib/dl/import.rb, line 19
      def [](name)
        return @SYM[name.to_s][0]
      end

[Source]

# File dl/lib/dl/import.rb, line 180
      def _args_
        return @args
      end

[Source]

# File dl/lib/dl/import.rb, line 184
      def _retval_
        return @retval
      end

example:

  callback "int method_name(int, char*)"

[Source]

# File dl/lib/dl/import.rb, line 67
      def callback(proto)
        func,ret,args = parse_cproto(proto)

        init_types()
        init_sym()

        rty,renc,rdec = @types.encode_return_type(ret)
        if( !rty )
          raise(TypeError, "unsupported type: #{ret}")
        end
        ty,enc,dec = encode_argument_types(args)
        symty = rty + ty

        module_eval("module_function :#{func}")
        sym = module_eval([
          "DL::callback(\"#{symty}\"){|*args|",
          "  sym,rdec,enc,dec  = @SYM['#{func}']",
          "  args = enc.call(args) if enc",
          "  r,rs = #{func}(*args)",
          "  r  = renc.call(r) if rdec",
          "  rs = dec.call(rs) if (dec && rs)",
          "  @retval = r",
          "  @args   = rs",
          "  @retval",
          "}",
        ].join("\n"))

        @SYM[func] = [sym,rdec,enc,dec]

        return sym
      end

[Source]

# File dl/lib/dl/struct.rb, line 9
      def define_struct(contents)
        init_types()
        Struct.new(@types, contents)
      end

[Source]

# File dl/lib/dl/struct.rb, line 15
      def define_union(contents)
        init_types()
        Union.new(@types, contents)
      end
dllink(*libnames)

Alias for dlload

[Source]

# File dl/lib/dl/import.rb, line 23
      def dlload(*libnames)
        if( !defined?(@LIBS) )
          @LIBS = []
        end
        libnames.each{|libname|
          if( !LIB_MAP[libname] )
            LIB_MAP[libname] = DL.dlopen(libname)
          end
          @LIBS.push(LIB_MAP[libname])
        }
      end

[Source]

# File dl/lib/dl/import.rb, line 188
      def encode_argument_types(tys)
        init_types()
        encty = []
        enc = nil
        dec = nil
        tys.each_with_index{|ty,idx|
          ty,c1,c2 = @types.encode_argument_type(ty)
          if( !ty )
            raise(TypeError, "unsupported type: #{ty}")
          end
          encty.push(ty)
          if( enc )
            if( c1 )
              conv1 = enc
              enc = proc{|v| v = conv1.call(v); v[idx] = c1.call(v[idx]); v}
            end
          else
            if( c1 )
              enc = proc{|v| v[idx] = c1.call(v[idx]); v}
            end
          end
          if( dec )
            if( c2 )
              conv2 = dec
              dec = proc{|v| v = conv2.call(v); v[idx] = c2.call(v[idx]); v}
            end
          else
            if( c2 )
              dec = proc{|v| v[idx] = c2.call(v[idx]); v}
            end
          end
        }
        return [encty.join, enc, dec]
      end

example:

  extern "int strlen(char*)"

[Source]

# File dl/lib/dl/import.rb, line 59
      def extern(proto)
        func,ret,args = parse_cproto(proto)
        return import(func, ret, args)
      end

example:

  import("get_length", "int", ["void*", "int"])

[Source]

# File dl/lib/dl/import.rb, line 134
      def import(name, rettype, argtypes = nil)
        init_types()
        init_sym()

        rty,_,rdec = @types.encode_return_type(rettype)
        if( !rty )
          raise(TypeError, "unsupported type: #{rettype}")
        end
        ty,enc,dec = encode_argument_types(argtypes)
        symty = rty + ty

        sym = symbol(name, symty)

        mname = name.dup
        if( ?A <= mname[0] && mname[0] <= ?Z )
          mname[0,1] = mname[0,1].downcase
        end
        @SYM[mname] = [sym,rdec,enc,dec]
        
        module_eval [
          "def #{mname}(*args)",
          "  sym,rdec,enc,dec  = @SYM['#{mname}']",
          "  args = enc.call(args) if enc",
          if( $DEBUG )
            "  p \"[DL] call #{mname} with \#{args.inspect}\""
          else
            ""
          end,
          "  r,rs = sym.call(*args)",
          if( $DEBUG )
            "  p \"[DL] retval=\#{r.inspect} args=\#{rs.inspect}\""
          else
            ""
          end,
          "  r  = rdec.call(r) if rdec",
          "  rs = dec.call(rs) if dec",
          "  @retval = r",
          "  @args   = rs",
          "  return @retval",
          "end",
          "module_function :#{mname}",
        ].join("\n")

        return sym
      end

[Source]

# File dl/lib/dl/import.rb, line 15
      def init_sym()
        @SYM ||= {}
      end

[Source]

# File dl/lib/dl/import.rb, line 11
      def init_types()
        @types ||= ::DL::Types.new
      end

[Source]

# File dl/lib/dl/import.rb, line 36
      def parse_cproto(proto)
        proto = proto.gsub(/\s+/, " ").strip
        case proto
        when /^([\d\w\*_\s]+)\(([\d\w\*_\s\,\[\]]*)\)$/
          ret = $1
          args = $2.strip()
          ret = ret.split(/\s+/)
          args = args.split(/\s*,\s*/)
          func = ret.pop()
          if( func =~ /^\*/ )
            func.gsub!(/^\*+/,"")
            ret.push("*")
          end
          ret  = ret.join(" ")
          return [func, ret, args]
        else
          raise(RuntimeError,"can't parse the function prototype: #{proto}")
        end
      end
struct(contents)

Alias for define_struct

example:

 symbol "foo_value"
 symbol "foo_func", "IIP"

[Source]

# File dl/lib/dl/import.rb, line 112
      def symbol(name, ty = nil)
        sym = nil
        @LIBS.each{|lib|
          begin
            if( ty )
              sym = lib[name, ty]
            else
              sym = lib[name]
            end
          rescue
            next
          end
        }
        if( !sym )
          raise(RuntimeError, "can't find the symbol `#{name}'")
        end
        return sym
      end

example:

 typealias("uint", "unsigned int")

[Source]

# File dl/lib/dl/import.rb, line 102
      def typealias(alias_type, ty1, enc1=nil, dec1=nil, ty2=nil, enc2=nil, dec2=nil)
        init_types()
        @types.typealias(alias_type, ty1, enc1, dec1,
                                     ty2||ty1, enc2, dec2)
      end
union(contents)

Alias for define_union

[Validate]