From 7bcc13550437e1c4198fbf6212abc8e7672e1adb Mon Sep 17 00:00:00 2001 From: ttate Date: Mon, 7 Feb 2005 09:45:02 +0000 Subject: [PATCH] Improved DL::Handle#sym. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@7911 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ext/dl/handle.c | 147 +++++++++++++++++++++++++-------------- ext/dl/lib/dl/cparser.rb | 2 +- ext/dl/lib/dl/func.rb | 4 +- ext/dl/lib/dl/import.rb | 5 +- ext/dl/lib/dl/value.rb | 7 ++ 5 files changed, 109 insertions(+), 56 deletions(-) diff --git a/ext/dl/handle.c b/ext/dl/handle.c index 7f5ce12168..d30105169c 100644 --- a/ext/dl/handle.c +++ b/ext/dl/handle.c @@ -125,64 +125,109 @@ rb_dlhandle_to_i(VALUE self) VALUE rb_dlhandle_sym(VALUE self, VALUE sym) { - void (*func)(); - struct sym_data *data; - struct dl_handle *dlhandle; - void *handle; - const char *name; - const char *err; + void (*func)(); + struct sym_data *data; + struct dl_handle *dlhandle; + void *handle; + const char *name; + const char *err; - rb_secure(2); + rb_secure(2); - if( sym == Qnil ){ + if( sym == Qnil ){ #if defined(RTLD_NEXT) - name = RTLD_NEXT; + name = RTLD_NEXT; #else - name = NULL; + name = NULL; #endif - } - else{ - name = StringValuePtr(sym); - } - - - Data_Get_Struct(self, struct dl_handle, dlhandle); - if( ! dlhandle->open ){ - rb_raise(rb_eDLError, "Closed handle."); - } - handle = dlhandle->ptr; - - func = dlsym(handle, name); -#if defined(HAVE_DLERROR) - if( !func && (err = dlerror()) ) -#else - if( !func ) -#endif - { -#if defined(__CYGWIN__) || defined(WIN32) || defined(__MINGW32__) - { - int len = strlen(name); - char *name_a = (char*)xmalloc(len+2); - strcpy(name_a, name); - name_a[len] = 'A'; - name_a[len+1] = '\0'; - func = dlsym(handle, name_a); - xfree(name_a); -#if defined(HAVE_DLERROR) - if( !func && (err = dlerror()) ) -#else - if( !func ) -#endif - { - rb_raise(rb_eDLError, "Unknown symbol \"%sA\".", name); - } } -#else - rb_raise(rb_eDLError, "Unknown symbol \"%s\".", name); -#endif - } + else{ + name = StringValuePtr(sym); + } - return PTR2NUM(func); + + Data_Get_Struct(self, struct dl_handle, dlhandle); + if( ! dlhandle->open ){ + rb_raise(rb_eDLError, "Closed handle."); + } + handle = dlhandle->ptr; + + func = dlsym(handle, name); +#if defined(HAVE_DLERROR) + if( !func && (err = dlerror()) ) +#else + if( !func ) +#endif + { +#if defined(__CYGWIN__) || defined(WIN32) || defined(__MINGW32__) + { + int len = strlen(name); + int i; + char *name_a = (char*)xmalloc(len+2); + strcpy(name_a, name); + name_a[len] = 'A'; + name_a[len+1] = '\0'; + func = dlsym(handle, name_a); + xfree(name_a); +#if defined(HAVE_DLERROR) + if( !func && (err = dlerror()) ) +#else + if( !func ) +#endif + { + 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 + 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); + } +#endif + } + + return PTR2NUM(func); } void diff --git a/ext/dl/lib/dl/cparser.rb b/ext/dl/lib/dl/cparser.rb index 5b5dd5f478..c897d1b69f 100644 --- a/ext/dl/lib/dl/cparser.rb +++ b/ext/dl/lib/dl/cparser.rb @@ -39,7 +39,7 @@ module DL tymap ||= {} signature = signature.gsub(/\s+/, " ").strip case signature - when /^([\d\w\*_\s]+)\(([\d\w\*_\s\,\[\]]*)\)$/ + when /^([\d\w@\*_\s]+)\(([\d\w\*_\s\,\[\]]*)\)$/ ret = $1 args = $2 ret = ret.split(/\s+/) diff --git a/ext/dl/lib/dl/func.rb b/ext/dl/lib/dl/func.rb index 121f2efcc0..b29aebcc8b 100644 --- a/ext/dl/lib/dl/func.rb +++ b/ext/dl/lib/dl/func.rb @@ -27,7 +27,7 @@ module DL def call(*args, &block) funcs = [] - args = wrap_args(args, nil, funcs, &block) + args = wrap_args(args, @stack.types, funcs, &block) r = @cfunc.call(@stack.pack(args)) funcs.each{|f| f.unbind_at_call()} return wrap_result(r) @@ -59,7 +59,7 @@ module DL end } r = block.call(*ary) - wrap_arg(r, nil, []) + wrap_arg(r, @cfunc.ctype, []) } case @cfunc.calltype when :cdecl diff --git a/ext/dl/lib/dl/import.rb b/ext/dl/lib/dl/import.rb index 2ad805598a..ebd84eb471 100644 --- a/ext/dl/lib/dl/import.rb +++ b/ext/dl/lib/dl/import.rb @@ -113,9 +113,10 @@ module DL private :parse_bind_options 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) - 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 #define_method(name){|*args,&block| f.call(*args,&block)} module_eval(<<-EOS) diff --git a/ext/dl/lib/dl/value.rb b/ext/dl/lib/dl/value.rb index 1357106a42..aa7e0dd325 100644 --- a/ext/dl/lib/dl/value.rb +++ b/ext/dl/lib/dl/value.rb @@ -50,6 +50,13 @@ module DL case arg when CPtr return arg.to_i + when IO + case ty + when TYPE_VOIDP + return CPtr[arg].to_i + else + return arg.to_i + end when Function if( block ) arg.bind_at_call(&block)