Improved DL::Handle#sym.

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@7911 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
ttate 2005-02-07 09:45:02 +00:00
parent 48a86f5ffa
commit 7bcc135504
5 changed files with 109 additions and 56 deletions

View File

@ -162,6 +162,7 @@ rb_dlhandle_sym(VALUE self, VALUE sym)
#if defined(__CYGWIN__) || defined(WIN32) || defined(__MINGW32__) #if defined(__CYGWIN__) || defined(WIN32) || defined(__MINGW32__)
{ {
int len = strlen(name); int len = strlen(name);
int i;
char *name_a = (char*)xmalloc(len+2); char *name_a = (char*)xmalloc(len+2);
strcpy(name_a, name); strcpy(name_a, name);
name_a[len] = 'A'; name_a[len] = 'A';
@ -174,11 +175,55 @@ rb_dlhandle_sym(VALUE self, VALUE sym)
if( !func ) if( !func )
#endif #endif
{ {
rb_raise(rb_eDLError, "Unknown symbol \"%sA\".", name); for( i = 0; i < 256; i += 4 ){
int len = strlen(name);
char *name_n = (char*)xmalloc(len+5);
sprintf(name_n, "%s@%d%c", name, i, 0);
func = dlsym(handle, name_n);
xfree(name_n);
#if defined(HAVE_DLERROR)
if( func || !(err = dlerror()) )
#else
if( func )
#endif
{
break;
}
}
#if defined(HAVE_DLERROR)
if( !func && (err = dlerror()) )
#else
if( !func )
#endif
{
rb_raise(rb_eDLError, "Unknown symbol \"%s\".", name);
}
} }
} }
#else #else
for( i = 0; i < 256; i += 4 ){
int len = strlen(name);
char *name_n = (char*)xmalloc(len+4);
sprintf(name_n, "%s@%d", name, i);
func = dlsym(handle, name_n);
xfree(name_n);
#if defined(HAVE_DLERROR)
if( func || !(err = dlerror()) )
#else
if( func )
#endif
{
break;
}
}
#if defined(HAVE_DLERROR)
if( !func && (err = dlerror()) )
#else
if( !func )
#endif
{
rb_raise(rb_eDLError, "Unknown symbol \"%s\".", name); rb_raise(rb_eDLError, "Unknown symbol \"%s\".", name);
}
#endif #endif
} }

View File

@ -39,7 +39,7 @@ module DL
tymap ||= {} tymap ||= {}
signature = signature.gsub(/\s+/, " ").strip signature = signature.gsub(/\s+/, " ").strip
case signature case signature
when /^([\d\w\*_\s]+)\(([\d\w\*_\s\,\[\]]*)\)$/ when /^([\d\w@\*_\s]+)\(([\d\w\*_\s\,\[\]]*)\)$/
ret = $1 ret = $1
args = $2 args = $2
ret = ret.split(/\s+/) ret = ret.split(/\s+/)

View File

@ -27,7 +27,7 @@ module DL
def call(*args, &block) def call(*args, &block)
funcs = [] funcs = []
args = wrap_args(args, nil, funcs, &block) args = wrap_args(args, @stack.types, funcs, &block)
r = @cfunc.call(@stack.pack(args)) r = @cfunc.call(@stack.pack(args))
funcs.each{|f| f.unbind_at_call()} funcs.each{|f| f.unbind_at_call()}
return wrap_result(r) return wrap_result(r)
@ -59,7 +59,7 @@ module DL
end end
} }
r = block.call(*ary) r = block.call(*ary)
wrap_arg(r, nil, []) wrap_arg(r, @cfunc.ctype, [])
} }
case @cfunc.calltype case @cfunc.calltype
when :cdecl when :cdecl

View File

@ -113,9 +113,10 @@ module DL
private :parse_bind_options private :parse_bind_options
def extern(signature, *opts) def extern(signature, *opts)
name, ctype, argtype = parse_signature(signature, @type_alias) symname, ctype, argtype = parse_signature(signature, @type_alias)
opt = parse_bind_options(opts) opt = parse_bind_options(opts)
f = import_function(name, ctype, argtype, opt[:call_type]) f = import_function(symname, ctype, argtype, opt[:call_type])
name = symname.gsub(/@.+/,'')
@func_map[name] = f @func_map[name] = f
#define_method(name){|*args,&block| f.call(*args,&block)} #define_method(name){|*args,&block| f.call(*args,&block)}
module_eval(<<-EOS) module_eval(<<-EOS)

View File

@ -50,6 +50,13 @@ module DL
case arg case arg
when CPtr when CPtr
return arg.to_i return arg.to_i
when IO
case ty
when TYPE_VOIDP
return CPtr[arg].to_i
else
return arg.to_i
end
when Function when Function
if( block ) if( block )
arg.bind_at_call(&block) arg.bind_at_call(&block)