# File dl/lib/dl/import.rb, line 18
def [](name)
return @SYM[name.to_s][0]
end
# File dl/lib/dl/import.rb, line 183
def _retval_
return @retval
end
example:
callback "int method_name(int, char*)"
# File dl/lib/dl/import.rb, line 66
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",
" r",
"}",
].join("\n"))
@SYM[func] = [sym,rdec,enc,dec]
return sym
end
# File dl/lib/dl/struct.rb, line 8
def define_struct(contents)
init_types()
Struct.new(@types, contents)
end
# File dl/lib/dl/struct.rb, line 14
def define_union(contents)
init_types()
Union.new(@types, contents)
end
# File dl/lib/dl/import.rb, line 22
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
# File dl/lib/dl/import.rb, line 187
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*)"
# File dl/lib/dl/import.rb, line 58
def extern(proto)
func,ret,args = parse_cproto(proto)
return import(func, ret, args)
end
example:
import("get_length", "int", ["void*", "int"])
# File dl/lib/dl/import.rb, line 133
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 r",
"end",
"module_function :#{mname}",
].join("\n")
return sym
end
# File dl/lib/dl/import.rb, line 14
def init_sym()
@SYM ||= {}
end
# File dl/lib/dl/import.rb, line 10
def init_types()
@types ||= ::DL::Types.new
end
# File dl/lib/dl/import.rb, line 35
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
example:
symbol "foo_value" symbol "foo_func", "IIP"
# File dl/lib/dl/import.rb, line 111
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")
# File dl/lib/dl/import.rb, line 101
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
Commenting is here to help enhance the documentation. For example, code samples, or clarification of the documentation.
If you have questions about Ruby or the documentation, please post to one of the Ruby mailing lists. You will get better, faster, help that way.
If you wish to post a correction of the docs, please do so, but also file bug report so that it can be corrected for the next release. Thank you.
If you want to help improve the Ruby documentation, please see Improve the docs, or visit Documenting-ruby.org.