Module: DL::Importable::Internal

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

### Methods

[] _args_ _retval_ callback define_struct define_union dllink dlload encode_argument_types extern import init_sym init_types parse_cproto struct symbol typealias union

### Classes and Modules

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

### Public Instance methods

[](name)

[Source]

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

_args_()

[Source]

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

_retval_()

[Source]

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

callback(proto)

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

define_struct(contents)

[Source]

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

define_union(contents)

[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

dlload(*libnames)

[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

encode_argument_types(tys)

[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

extern(proto)

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

import(name, rettype, argtypes = nil)

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

init_sym()

[Source]

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

init_types()

[Source]

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

parse_cproto(proto)

[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

symbol(name, ty = nil)

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

typealias(alias_type, ty1, enc1=nil, dec1=nil, ty2=nil, enc2=nil, dec2=nil)

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]