summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortenderlove <tenderlove@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2012-11-27 05:59:34 +0000
committertenderlove <tenderlove@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2012-11-27 05:59:34 +0000
commit1eac1cb21ebb095886393ee71acd0ed8f6dedab8 (patch)
tree5200317a05b1ae0a676f02ff206f2b5dc6b10b87
parent1d8d7a3eec54a5440a1942c0b589c228138834ae (diff)
reverting r37881
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@37891 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r--ChangeLog24
-rw-r--r--ext/dl/lib/dl/struct.rb2
-rw-r--r--ext/fiddle/extconf.rb14
-rw-r--r--ext/fiddle/fiddle.c198
-rw-r--r--ext/fiddle/fiddle.h27
-rw-r--r--ext/fiddle/function.c12
-rw-r--r--ext/fiddle/handle.c465
-rw-r--r--ext/fiddle/lib/fiddle.rb16
-rw-r--r--ext/fiddle/lib/fiddle/function.rb7
-rw-r--r--ext/fiddle/pointer.c691
-rw-r--r--test/dl/test_callback.rb2
-rw-r--r--test/fiddle/helper.rb5
-rw-r--r--test/fiddle/test_closure.rb4
-rw-r--r--test/fiddle/test_fiddle.rb21
-rw-r--r--test/fiddle/test_func.rb79
-rw-r--r--test/fiddle/test_handle.rb186
-rw-r--r--test/fiddle/test_pointer.rb231
17 files changed, 33 insertions, 1951 deletions
diff --git a/ChangeLog b/ChangeLog
index e0763c7fa3..7fd98acf7f 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -46,30 +46,6 @@ Tue Nov 27 09:24:47 2012 KOSAKI Motohiro <kosaki.motohiro@gmail.com>
test for the above.
* NEWS: news for the above.
-Tue Nov 27 10:37:44 2012 Aaron Patterson <aaron@tenderlovemaking.com>
-
- * ext/fiddle/handle.c: Make Fiddle independent of DL, copy DL::Handle
- to Fiddle::Handle.
- * ext/fiddle/pointer.c: Make Fiddle independent of DL, copy
- DL::Pointer to Fiddle::Pointer.
- * test/fiddle/test_func.rb: relevent tests
- * test/fiddle/test_handle.rb: ditto
- * test/fiddle/test_pointer.rb: ditto
- * ext/dl/lib/dl/struct.rb: use Fiddle::Pointer if available
- * ext/fiddle/extconf.rb: check for dlfcn.h
- * ext/fiddle/fiddle.c: add constants for sizeof() things
- * ext/fiddle/fiddle.h: include dlfcn.h
- * ext/fiddle/function.c: expose a C function for creating new
- Fiddle::Function objects.
- * ext/fiddle/lib/fiddle.rb: include constants for dl backwards compat
- * ext/fiddle/lib/fiddle/function.rb: read the pointer from the
- function for dl backwards compat.
- * test/dl/test_callback.rb: check the addresses of the pointers rather
- than their types.
- * test/fiddle/helper.rb: remove dependency on dl
- * test/fiddle/test_closure.rb: ditto
- * test/fiddle/test_fiddle.rb: ditto
-
Tue Nov 27 09:59:16 2012 Nobuyoshi Nakada <nobu@ruby-lang.org>
* ext/extmk.rb (extmake): close mkmf.log for each libraries so that
diff --git a/ext/dl/lib/dl/struct.rb b/ext/dl/lib/dl/struct.rb
index e2d91a6d14..9359ca4fcc 100644
--- a/ext/dl/lib/dl/struct.rb
+++ b/ext/dl/lib/dl/struct.rb
@@ -76,7 +76,7 @@ module DL
end
# A C struct wrapper
- class CStructEntity < (DL.fiddle? ? Fiddle::Pointer : CPtr)
+ class CStructEntity < CPtr
include PackInfo
include ValueUtil
diff --git a/ext/fiddle/extconf.rb b/ext/fiddle/extconf.rb
index 9b9803f65b..a9cdcc251f 100644
--- a/ext/fiddle/extconf.rb
+++ b/ext/fiddle/extconf.rb
@@ -19,20 +19,6 @@ end
have_header 'sys/mman.h'
-if have_header "dlfcn.h"
- have_library "dl"
-
- %w{ dlopen dlclose dlsym }.each do |func|
- abort "missing function #{func}" unless have_func(func)
- end
-
- have_func "dlerror"
-elsif have_header "windows.h"
- %w{ LoadLibrary FreeLibrary GetProcAddress }.each do |func|
- abort "missing function #{func}" unless have_func(func)
- end
-end
-
config = File.read(RbConfig.expand(File.join($arch_hdrdir, "ruby/config.h")))
types = {"SIZE_T"=>"SSIZE_T", "PTRDIFF_T"=>nil, "INTPTR_T"=>nil}
types.each do |type, signed|
diff --git a/ext/fiddle/fiddle.c b/ext/fiddle/fiddle.c
index 85a362cb04..3006bbeb77 100644
--- a/ext/fiddle/fiddle.c
+++ b/ext/fiddle/fiddle.c
@@ -1,7 +1,6 @@
#include <fiddle.h>
VALUE mFiddle;
-VALUE rb_eFiddleError;
#ifndef TYPE_SSIZE_T
# if SIZEOF_SIZE_T == SIZEOF_INT
@@ -35,100 +34,6 @@ VALUE rb_eFiddleError;
#endif
#define TYPE_UINTPTR_T (-TYPE_INTPTR_T)
-void Init_fiddle_pointer(void);
-
-/*
- * call-seq: Fiddle.malloc(size)
- *
- * Allocate +size+ bytes of memory and return the integer memory address
- * for the allocated memory.
- */
-static VALUE
-rb_fiddle_malloc(VALUE self, VALUE size)
-{
- void *ptr;
-
- rb_secure(4);
- ptr = (void*)ruby_xmalloc(NUM2INT(size));
- return PTR2NUM(ptr);
-}
-
-/*
- * call-seq: Fiddle.realloc(addr, size)
- *
- * Change the size of the memory allocated at the memory location +addr+ to
- * +size+ bytes. Returns the memory address of the reallocated memory, which
- * may be different than the address passed in.
- */
-static VALUE
-rb_fiddle_realloc(VALUE self, VALUE addr, VALUE size)
-{
- void *ptr = NUM2PTR(addr);
-
- rb_secure(4);
- ptr = (void*)ruby_xrealloc(ptr, NUM2INT(size));
- return PTR2NUM(ptr);
-}
-
-/*
- * call-seq: Fiddle.free(addr)
- *
- * Free the memory at address +addr+
- */
-VALUE
-rb_fiddle_free(VALUE self, VALUE addr)
-{
- void *ptr = NUM2PTR(addr);
-
- rb_secure(4);
- ruby_xfree(ptr);
- return Qnil;
-}
-
-/*
- * call-seq: Fiddle.dlunwrap(addr)
- *
- * Returns the hexadecimal representation of a memory pointer address +addr+
- *
- * Example:
- *
- * lib = Fiddle.dlopen('/lib64/libc-2.15.so')
- * => #<Fiddle::Handle:0x00000001342460>
- *
- * lib['strcpy'].to_s(16)
- * => "7f59de6dd240"
- *
- * Fiddle.dlunwrap(Fiddle.dlwrap(lib['strcpy'].to_s(16)))
- * => "7f59de6dd240"
- */
-VALUE
-rb_fiddle_ptr2value(VALUE self, VALUE addr)
-{
- rb_secure(4);
- return (VALUE)NUM2PTR(addr);
-}
-
-/*
- * call-seq: Fiddle.dlwrap(val)
- *
- * Returns a memory pointer of a function's hexadecimal address location +val+
- *
- * Example:
- *
- * lib = Fiddle.dlopen('/lib64/libc-2.15.so')
- * => #<Fiddle::Handle:0x00000001342460>
- *
- * Fiddle.dlwrap(lib['strcpy'].to_s(16))
- * => 25522520
- */
-static VALUE
-rb_fiddle_value2ptr(VALUE self, VALUE val)
-{
- return PTR2NUM((void*)val);
-}
-
-void Init_fiddle_handle(void);
-
void
Init_fiddle(void)
{
@@ -142,13 +47,6 @@ Init_fiddle(void)
*/
mFiddle = rb_define_module("Fiddle");
- /*
- * Document-class: Fiddle::DLError
- *
- * standard dynamic load exception
- */
- rb_eFiddleError = rb_define_class_under(mFiddle, "DLError", rb_eStandardError);
-
/* Document-const: TYPE_VOID
*
* C type - void
@@ -245,103 +143,7 @@ Init_fiddle(void)
rb_define_const(mFiddle, "WINDOWS", Qfalse);
#endif
- /* Document-const: SIZEOF_VOIDP
- *
- * size of a void*
- */
- rb_define_const(mFiddle, "SIZEOF_VOIDP", INT2NUM(sizeof(void*)));
-
- /* Document-const: SIZEOF_CHAR
- *
- * size of a char
- */
- rb_define_const(mFiddle, "SIZEOF_CHAR", INT2NUM(sizeof(char)));
-
- /* Document-const: SIZEOF_SHORT
- *
- * size of a short
- */
- rb_define_const(mFiddle, "SIZEOF_SHORT", INT2NUM(sizeof(short)));
-
- /* Document-const: SIZEOF_INT
- *
- * size of an int
- */
- rb_define_const(mFiddle, "SIZEOF_INT", INT2NUM(sizeof(int)));
-
- /* Document-const: SIZEOF_LONG
- *
- * size of a long
- */
- rb_define_const(mFiddle, "SIZEOF_LONG", INT2NUM(sizeof(long)));
-
-#if HAVE_LONG_LONG
- /* Document-const: SIZEOF_LONG_LONG
- *
- * size of a long long
- */
- rb_define_const(mFiddle, "SIZEOF_LONG_LONG", INT2NUM(sizeof(LONG_LONG)));
-#endif
-
- /* Document-const: SIZEOF_FLOAT
- *
- * size of a float
- */
- rb_define_const(mFiddle, "SIZEOF_FLOAT", INT2NUM(sizeof(float)));
-
- /* Document-const: SIZEOF_DOUBLE
- *
- * size of a double
- */
- rb_define_const(mFiddle, "SIZEOF_DOUBLE",INT2NUM(sizeof(double)));
-
- /* Document-const: SIZEOF_SIZE_T
- *
- * size of a size_t
- */
- rb_define_const(mFiddle, "SIZEOF_SIZE_T", INT2NUM(sizeof(size_t)));
-
- /* Document-const: SIZEOF_SSIZE_T
- *
- * size of a ssize_t
- */
- rb_define_const(mFiddle, "SIZEOF_SSIZE_T", INT2NUM(sizeof(size_t))); /* same as size_t */
-
- /* Document-const: SIZEOF_PTRDIFF_T
- *
- * size of a ptrdiff_t
- */
- rb_define_const(mFiddle, "SIZEOF_PTRDIFF_T", INT2NUM(sizeof(ptrdiff_t)));
-
- /* Document-const: SIZEOF_INTPTR_T
- *
- * size of a intptr_t
- */
- rb_define_const(mFiddle, "SIZEOF_INTPTR_T", INT2NUM(sizeof(intptr_t)));
-
- /* Document-const: SIZEOF_UINTPTR_T
- *
- * size of a uintptr_t
- */
- rb_define_const(mFiddle, "SIZEOF_UINTPTR_T", INT2NUM(sizeof(uintptr_t)));
-
- rb_define_module_function(mFiddle, "dlwrap", rb_fiddle_value2ptr, 1);
-
- /* Document-const: RUBY_FREE
- *
- * Address of the ruby_xfree() function
- */
- rb_define_const(mFiddle, "RUBY_FREE", PTR2NUM(ruby_xfree));
-
- rb_define_module_function(mFiddle, "dlwrap", rb_fiddle_value2ptr, 1);
- rb_define_module_function(mFiddle, "dlunwrap", rb_fiddle_ptr2value, 1);
- rb_define_module_function(mFiddle, "malloc", rb_fiddle_malloc, 1);
- rb_define_module_function(mFiddle, "realloc", rb_fiddle_realloc, 2);
- rb_define_module_function(mFiddle, "free", rb_fiddle_free, 1);
-
Init_fiddle_function();
Init_fiddle_closure();
- Init_fiddle_handle();
- Init_fiddle_pointer();
}
/* vim: set noet sws=4 sw=4: */
diff --git a/ext/fiddle/fiddle.h b/ext/fiddle/fiddle.h
index 8c8a93425b..3a829fe433 100644
--- a/ext/fiddle/fiddle.h
+++ b/ext/fiddle/fiddle.h
@@ -12,30 +12,6 @@
#include <sys/mman.h>
#endif
-#if defined(HAVE_DLFCN_H)
-# include <dlfcn.h>
-# /* some stranger systems may not define all of these */
-#ifndef RTLD_LAZY
-#define RTLD_LAZY 0
-#endif
-#ifndef RTLD_GLOBAL
-#define RTLD_GLOBAL 0
-#endif
-#ifndef RTLD_NOW
-#define RTLD_NOW 0
-#endif
-#else
-# if defined(_WIN32)
-# include <windows.h>
-# define dlopen(name,flag) ((void*)LoadLibrary(name))
-# define dlerror() strerror(rb_w32_map_errno(GetLastError()))
-# define dlsym(handle,name) ((void*)GetProcAddress((handle),(name)))
-# define RTLD_LAZY -1
-# define RTLD_NOW -1
-# define RTLD_GLOBAL -1
-# endif
-#endif
-
#ifdef USE_HEADER_HACKS
#include <ffi/ffi.h>
#else
@@ -122,9 +98,6 @@
#define TYPE_DOUBLE 8
extern VALUE mFiddle;
-extern VALUE rb_eFiddleError;
-
-VALUE rb_fiddle_new_function(VALUE address, VALUE arg_types, VALUE ret_type);
#endif
/* vim: set noet sws=4 sw=4: */
diff --git a/ext/fiddle/function.c b/ext/fiddle/function.c
index 7fc5127f9f..6e8909991a 100644
--- a/ext/fiddle/function.c
+++ b/ext/fiddle/function.c
@@ -38,18 +38,6 @@ allocate(VALUE klass)
return TypedData_Make_Struct(klass, ffi_cif, &function_data_type, cif);
}
-VALUE
-rb_fiddle_new_function(VALUE address, VALUE arg_types, VALUE ret_type)
-{
- VALUE argv[3];
-
- argv[0] = address;
- argv[1] = arg_types;
- argv[2] = ret_type;
-
- return rb_class_new_instance(3, argv, cFiddleFunction);
-}
-
static VALUE
initialize(int argc, VALUE argv[], VALUE self)
{
diff --git a/ext/fiddle/handle.c b/ext/fiddle/handle.c
deleted file mode 100644
index 7031f5f77c..0000000000
--- a/ext/fiddle/handle.c
+++ /dev/null
@@ -1,465 +0,0 @@
-#include <ruby.h>
-#include <fiddle.h>
-
-VALUE rb_cHandle;
-
-struct dl_handle {
- void *ptr;
- int open;
- int enable_close;
-};
-
-#ifdef _WIN32
-# ifndef _WIN32_WCE
-static void *
-w32_coredll(void)
-{
- MEMORY_BASIC_INFORMATION m;
- memset(&m, 0, sizeof(m));
- if( !VirtualQuery(_errno, &m, sizeof(m)) ) return NULL;
- return m.AllocationBase;
-}
-# endif
-
-static int
-w32_dlclose(void *ptr)
-{
-# ifndef _WIN32_WCE
- if( ptr == w32_coredll() ) return 0;
-# endif
- if( FreeLibrary((HMODULE)ptr) ) return 0;
- return errno = rb_w32_map_errno(GetLastError());
-}
-#define dlclose(ptr) w32_dlclose(ptr)
-#endif
-
-static void
-dlhandle_free(void *ptr)
-{
- struct dl_handle *dlhandle = ptr;
- if( dlhandle->ptr && dlhandle->open && dlhandle->enable_close ){
- dlclose(dlhandle->ptr);
- }
-}
-
-static size_t
-dlhandle_memsize(const void *ptr)
-{
- return ptr ? sizeof(struct dl_handle) : 0;
-}
-
-static const rb_data_type_t dlhandle_data_type = {
- "dl/handle",
- {0, dlhandle_free, dlhandle_memsize,},
-};
-
-/*
- * call-seq: close
- *
- * Close this Fiddle::Handle. Calling close more than once will raise a
- * Fiddle::DLError exception.
- */
-VALUE
-rb_dlhandle_close(VALUE self)
-{
- struct dl_handle *dlhandle;
-
- TypedData_Get_Struct(self, struct dl_handle, &dlhandle_data_type, dlhandle);
- if(dlhandle->open) {
- int ret = dlclose(dlhandle->ptr);
- dlhandle->open = 0;
-
- /* Check dlclose for successful return value */
- if(ret) {
-#if defined(HAVE_DLERROR)
- rb_raise(rb_eFiddleError, "%s", dlerror());
-#else
- rb_raise(rb_eFiddleError, "could not close handle");
-#endif
- }
- return INT2NUM(ret);
- }
- rb_raise(rb_eFiddleError, "dlclose() called too many times");
-
- UNREACHABLE;
-}
-
-VALUE
-rb_dlhandle_s_allocate(VALUE klass)
-{
- VALUE obj;
- struct dl_handle *dlhandle;
-
- obj = TypedData_Make_Struct(rb_cHandle, struct dl_handle, &dlhandle_data_type, dlhandle);
- dlhandle->ptr = 0;
- dlhandle->open = 0;
- dlhandle->enable_close = 0;
-
- return obj;
-}
-
-static VALUE
-predefined_dlhandle(void *handle)
-{
- VALUE obj = rb_dlhandle_s_allocate(rb_cHandle);
- struct dl_handle *dlhandle = DATA_PTR(obj);
-
- dlhandle->ptr = handle;
- dlhandle->open = 1;
- OBJ_FREEZE(obj);
- return obj;
-}
-
-/*
- * call-seq:
- * initialize(lib = nil, flags = Fiddle::RTLD_LAZY | Fiddle::RTLD_GLOBAL)
- *
- * Create a new handler that opens library named +lib+ with +flags+. If no
- * library is specified, RTLD_DEFAULT is used.
- */
-VALUE
-rb_dlhandle_initialize(int argc, VALUE argv[], VALUE self)
-{
- void *ptr;
- struct dl_handle *dlhandle;
- VALUE lib, flag;
- char *clib;
- int cflag;
- const char *err;
-
- switch( rb_scan_args(argc, argv, "02", &lib, &flag) ){
- case 0:
- clib = NULL;
- cflag = RTLD_LAZY | RTLD_GLOBAL;
- break;
- case 1:
- clib = NIL_P(lib) ? NULL : StringValuePtr(lib);
- cflag = RTLD_LAZY | RTLD_GLOBAL;
- break;
- case 2:
- clib = NIL_P(lib) ? NULL : StringValuePtr(lib);
- cflag = NUM2INT(flag);
- break;
- default:
- rb_bug("rb_dlhandle_new");
- }
-
- rb_secure(2);
-
-#if defined(_WIN32)
- if( !clib ){
- HANDLE rb_libruby_handle(void);
- ptr = rb_libruby_handle();
- }
- else if( STRCASECMP(clib, "libc") == 0
-# ifdef RUBY_COREDLL
- || STRCASECMP(clib, RUBY_COREDLL) == 0
- || STRCASECMP(clib, RUBY_COREDLL".dll") == 0
-# endif
- ){
-# ifdef _WIN32_WCE
- ptr = dlopen("coredll.dll", cflag);
-# else
- ptr = w32_coredll();
-# endif
- }
- else
-#endif
- ptr = dlopen(clib, cflag);
-#if defined(HAVE_DLERROR)
- if( !ptr && (err = dlerror()) ){
- rb_raise(rb_eFiddleError, "%s", err);
- }
-#else
- if( !ptr ){
- err = dlerror();
- rb_raise(rb_eFiddleError, "%s", err);
- }
-#endif
- TypedData_Get_Struct(self, struct dl_handle, &dlhandle_data_type, dlhandle);
- if( dlhandle->ptr && dlhandle->open && dlhandle->enable_close ){
- dlclose(dlhandle->ptr);
- }
- dlhandle->ptr = ptr;
- dlhandle->open = 1;
- dlhandle->enable_close = 0;
-
- if( rb_block_given_p() ){
- rb_ensure(rb_yield, self, rb_dlhandle_close, self);
- }
-
- return Qnil;
-}
-
-/*
- * call-seq: enable_close
- *
- * Enable a call to dlclose() when this Fiddle::Handle is garbage collected.
- */
-VALUE
-rb_dlhandle_enable_close(VALUE self)
-{
- struct dl_handle *dlhandle;
-
- TypedData_Get_Struct(self, struct dl_handle, &dlhandle_data_type, dlhandle);
- dlhandle->enable_close = 1;
- return Qnil;
-}
-
-/*
- * call-seq: disable_close
- *
- * Disable a call to dlclose() when this Fiddle::Handle is garbage collected.
- */
-VALUE
-rb_dlhandle_disable_close(VALUE self)
-{
- struct dl_handle *dlhandle;
-
- TypedData_Get_Struct(self, struct dl_handle, &dlhandle_data_type, dlhandle);
- dlhandle->enable_close = 0;
- return Qnil;
-}
-
-/*
- * call-seq: close_enabled?
- *
- * Returns +true+ if dlclose() will be called when this Fiddle::Handle is
- * garbage collected.
- */
-static VALUE
-rb_dlhandle_close_enabled_p(VALUE self)
-{
- struct dl_handle *dlhandle;
-
- TypedData_Get_Struct(self, struct dl_handle, &dlhandle_data_type, dlhandle);
-
- if(dlhandle->enable_close) return Qtrue;
- return Qfalse;
-}
-
-/*
- * call-seq: to_i
- *
- * Returns the memory address for this handle.
- */
-VALUE
-rb_dlhandle_to_i(VALUE self)
-{
- struct dl_handle *dlhandle;
-
- TypedData_Get_Struct(self, struct dl_handle, &dlhandle_data_type, dlhandle);
- return PTR2NUM(dlhandle);
-}
-
-static VALUE dlhandle_sym(void *handle, const char *symbol);
-
-/*
- * Document-method: sym
- * Document-method: []
- *
- * call-seq: sym(name)
- *
- * Get the address as an Integer for the function named +name+.
- */
-VALUE
-rb_dlhandle_sym(VALUE self, VALUE sym)
-{
- struct dl_handle *dlhandle;
-
- TypedData_Get_Struct(self, struct dl_handle, &dlhandle_data_type, dlhandle);
- if( ! dlhandle->open ){
- rb_raise(rb_eFiddleError, "closed handle");
- }
-
- return dlhandle_sym(dlhandle->ptr, StringValueCStr(sym));
-}
-
-#ifndef RTLD_NEXT
-#define RTLD_NEXT NULL
-#endif
-#ifndef RTLD_DEFAULT
-#define RTLD_DEFAULT NULL
-#endif
-
-/*
- * Document-method: sym
- * Document-method: []
- *
- * call-seq: sym(name)
- *
- * Get the address as an Integer for the function named +name+. The function
- * is searched via dlsym on RTLD_NEXT. See man(3) dlsym() for more info.
- */
-VALUE
-rb_dlhandle_s_sym(VALUE self, VALUE sym)
-{
- return dlhandle_sym(RTLD_NEXT, StringValueCStr(sym));
-}
-
-static VALUE
-dlhandle_sym(void *handle, const char *name)
-{
-#if defined(HAVE_DLERROR)
- const char *err;
-# define CHECK_DLERROR if( err = dlerror() ){ func = 0; }
-#else
-# define CHECK_DLERROR
-#endif
- void (*func)();
-
- rb_secure(2);
-#ifdef HAVE_DLERROR
- dlerror();
-#endif
- func = (void (*)())(VALUE)dlsym(handle, name);
- CHECK_DLERROR;
-#if defined(FUNC_STDCALL)
- if( !func ){
- int i;
- int len = (int)strlen(name);
- char *name_n;
-#if defined(__CYGWIN__) || defined(_WIN32) || defined(__MINGW32__)
- {
- char *name_a = (char*)xmalloc(len+2);
- strcpy(name_a, name);
- name_n = name_a;
- name_a[len] = 'A';
- name_a[len+1] = '\0';
- func = dlsym(handle, name_a);
- CHECK_DLERROR;
- if( func ) goto found;
- name_n = xrealloc(name_a, len+6);
- }
-#else
- name_n = (char*)xmalloc(len+6);
-#endif
- memcpy(name_n, name, len);
- name_n[len++] = '@';
- for( i = 0; i < 256; i += 4 ){
- sprintf(name_n + len, "%d", i);
- func = dlsym(handle, name_n);
- CHECK_DLERROR;
- if( func ) break;
- }
- if( func ) goto found;
- name_n[len-1] = 'A';
- name_n[len++] = '@';
- for( i = 0; i < 256; i += 4 ){
- sprintf(name_n + len, "%d", i);
- func = dlsym(handle, name_n);
- CHECK_DLERROR;
- if( func ) break;
- }
- found:
- xfree(name_n);
- }
-#endif
- if( !func ){
- rb_raise(rb_eFiddleError, "unknown symbol \"%s\"", name);
- }
-
- return PTR2NUM(func);
-}
-
-void
-Init_fiddle_handle(void)
-{
- /*
- * Document-class: Fiddle::Handle
- *
- * The Fiddle::Handle is the manner to access the dynamic library
- *
- * == Example
- *
- * === Setup
- *
- * libc_so = "/lib64/libc.so.6"
- * => "/lib64/libc.so.6"
- * @handle = Fiddle::Handle.new(libc_so)
- * => #<Fiddle::Handle:0x00000000d69ef8>
- *
- * === Setup, with flags
- *
- * libc_so = "/lib64/libc.so.6"
- * => "/lib64/libc.so.6"
- * @handle = Fiddle::Handle.new(libc_so, Fiddle::RTLD_LAZY | Fiddle::RTLD_GLOBAL)
- * => #<Fiddle::Handle:0x00000000d69ef8>
- *
- * === Addresses to symbols
- *
- * strcpy_addr = @handle['strcpy']
- * => 140062278451968
- *
- * or
- *
- * strcpy_addr = @handle.sym('strcpy')
- * => 140062278451968
- *
- */
- rb_cHandle = rb_define_class_under(mFiddle, "Handle", rb_cObject);
- rb_define_alloc_func(rb_cHandle, rb_dlhandle_s_allocate);
- rb_define_singleton_method(rb_cHandle, "sym", rb_dlhandle_s_sym, 1);
- rb_define_singleton_method(rb_cHandle, "[]", rb_dlhandle_s_sym, 1);
-
- /* Document-const: NEXT
- *
- * A predefined pseudo-handle of RTLD_NEXT
- *
- * Which will find the next occurrence of a function in the search order
- * after the current library.
- */
- rb_define_const(rb_cHandle, "NEXT", predefined_dlhandle(RTLD_NEXT));
-
- /* Document-const: DEFAULT
- *
- * A predefined pseudo-handle of RTLD_DEFAULT
- *
- * Which will find the first occurrence of the desired symbol using the
- * default library search order
- */
- rb_define_const(rb_cHandle, "DEFAULT", predefined_dlhandle(RTLD_DEFAULT));
-
- /* Document-const: RTLD_GLOBAL
- *
- * rtld Fiddle::Handle flag.
- *
- * The symbols defined by this library will be made available for symbol
- * resolution of subsequently loaded libraries.
- */
- rb_define_const(rb_cHandle, "RTLD_GLOBAL", INT2NUM(RTLD_GLOBAL));
-
- /* Document-const: RTLD_LAZY
- *
- * rtld Fiddle::Handle flag.
- *
- * Perform lazy binding. Only resolve symbols as the code that references
- * them is executed. If the symbol is never referenced, then it is never
- * resolved. (Lazy binding is only performed for function references;
- * references to variables are always immediately bound when the library
- * is loaded.)
- */
- rb_define_const(rb_cHandle, "RTLD_LAZY", INT2NUM(RTLD_LAZY));
-
- /* Document-const: RTLD_NOW
- *
- * rtld Fiddle::Handle flag.
- *
- * If this value is specified or the environment variable LD_BIND_NOW is
- * set to a nonempty string, all undefined symbols in the library are
- * resolved before dlopen() returns. If this cannot be done an error is
- * returned.
- */
- rb_define_const(rb_cHandle, "RTLD_NOW", INT2NUM(RTLD_NOW));
-
- rb_define_method(rb_cHandle, "initialize", rb_dlhandle_initialize, -1);
- rb_define_method(rb_cHandle, "to_i", rb_dlhandle_to_i, 0);
- rb_define_method(rb_cHandle, "close", rb_dlhandle_close, 0);
- rb_define_method(rb_cHandle, "sym", rb_dlhandle_sym, 1);
- rb_define_method(rb_cHandle, "[]", rb_dlhandle_sym, 1);
- rb_define_method(rb_cHandle, "disable_close", rb_dlhandle_disable_close, 0);
- rb_define_method(rb_cHandle, "enable_close", rb_dlhandle_enable_close, 0);
- rb_define_method(rb_cHandle, "close_enabled?", rb_dlhandle_close_enabled_p, 0);
-}
-
-/* vim: set noet sws=4 sw=4: */
diff --git a/ext/fiddle/lib/fiddle.rb b/ext/fiddle/lib/fiddle.rb
index 1c68b7b0ec..7d55a1f7ad 100644
--- a/ext/fiddle/lib/fiddle.rb
+++ b/ext/fiddle/lib/fiddle.rb
@@ -1,8 +1,13 @@
require 'fiddle.so'
require 'fiddle/function'
require 'fiddle/closure'
+require 'dl' unless Object.const_defined?(:DL)
module Fiddle
+
+ # A reference to DL::CPtr
+ Pointer = DL::CPtr
+
if WINDOWS
# Returns the last win32 +Error+ of the current executing +Thread+ or nil
# if none
@@ -26,15 +31,4 @@ module Fiddle
Thread.current[:__DL2_LAST_ERROR__] = error
Thread.current[:__FIDDLE_LAST_ERROR__] = error
end
-
- def dlopen library
- Fiddle::Handle.new library
- end
- module_function :dlopen
-
- # Add constants for backwards compat
-
- RTLD_GLOBAL = Handle::RTLD_GLOBAL # :nodoc:
- RTLD_LAZY = Handle::RTLD_LAZY # :nodoc:
- RTLD_NOW = Handle::RTLD_NOW # :nodoc:
end
diff --git a/ext/fiddle/lib/fiddle/function.rb b/ext/fiddle/lib/fiddle/function.rb
index f4d41e6a82..1657682498 100644
--- a/ext/fiddle/lib/fiddle/function.rb
+++ b/ext/fiddle/lib/fiddle/function.rb
@@ -2,12 +2,5 @@ module Fiddle
class Function
# The ABI of the Function.
attr_reader :abi
-
- # The address of this function
- attr_reader :ptr
-
- def to_i
- ptr.to_i
- end
end
end
diff --git a/ext/fiddle/pointer.c b/ext/fiddle/pointer.c
deleted file mode 100644
index a06f60ca79..0000000000
--- a/ext/fiddle/pointer.c
+++ /dev/null
@@ -1,691 +0,0 @@
-/* -*- C -*-
- * $Id$
- */
-
-#include <ruby/ruby.h>
-#include <ruby/io.h>
-#include <ctype.h>
-#include <fiddle.h>
-
-VALUE rb_cPointer;
-
-typedef void (*freefunc_t)(void*);
-
-struct ptr_data {
- void *ptr;
- long size;
- freefunc_t free;
- VALUE wrap[2];
-};
-
-#define RPTR_DATA(obj) ((struct ptr_data *)(DATA_PTR(obj)))
-
-static inline freefunc_t
-get_freefunc(VALUE func, volatile VALUE *wrap)
-{
- VALUE addrnum;
- if (NIL_P(func)) {
- *wrap = 0;
- return NULL;
- }
- addrnum = rb_Integer(func);
- *wrap = (addrnum != func) ? func : 0;
- return (freefunc_t)(VALUE)NUM2PTR(addrnum);
-}
-
-static ID id_to_ptr;
-
-static void
-dlptr_mark(void *ptr)
-{
- struct ptr_data *data = ptr;
- if (data->wrap[0]) {
- rb_gc_mark(data->wrap[0]);
- }
- if (data->wrap[1]) {
- rb_gc_mark(data->wrap[1]);
- }
-}
-
-static void
-dlptr_free(void *ptr)
-{
- struct ptr_data *data = ptr;
- if (data->ptr) {
- if (data->free) {
- (*(data->free))(data->ptr);
- }
- }
-}
-
-static size_t
-dlptr_memsize(const void *ptr)
-{
- const struct ptr_data *data = ptr;
- return data ? sizeof(*data) + data->size : 0;
-}
-
-static const rb_data_type_t dlptr_data_type = {
- "fiddle/pointer",
- {dlptr_mark, dlptr_free, dlptr_memsize,},
-};
-
-VALUE
-rb_dlptr_new2(VALUE klass, void *ptr, long size, freefunc_t func)
-{
- struct ptr_data *data;
- VALUE val;
-
- rb_secure(4);
- val = TypedData_Make_Struct(klass, struct ptr_data, &dlptr_data_type, data);
- data->ptr = ptr;
- data->free = func;
- data->size = size;
- OBJ_TAINT(val);
-
- return val;
-}
-
-VALUE
-rb_dlptr_new(void *ptr, long size, freefunc_t func)
-{
- return rb_dlptr_new2(rb_cPointer, ptr, size, func);
-}
-
-VALUE
-rb_dlptr_malloc(long size, freefunc_t func)
-{
- void *ptr;
-
- rb_secure(4);
- ptr = ruby_xmalloc((size_t)size);
- memset(ptr,0,(size_t)size);
- return rb_dlptr_new(ptr, size, func);
-}
-
-void *
-rb_dlptr2cptr(VALUE val)
-{
- struct ptr_data *data;
- void *ptr;
-
- if (rb_obj_is_kind_of(val, rb_cPointer)) {
- TypedData_Get_Struct(val, struct ptr_data, &dlptr_data_type, data);
- ptr = data->ptr;
- }
- else if (val == Qnil) {
- ptr = NULL;
- }
- else{
- rb_raise(rb_eTypeError, "DL::PtrData was expected");
- }
-
- return ptr;
-}
-
-static VALUE
-rb_dlptr_s_allocate(VALUE klass)
-{
- VALUE obj;
- struct ptr_data *data;
-
- rb_secure(4);
- obj = TypedData_Make_Struct(klass, struct ptr_data, &dlptr_data_type, data);
- data->ptr = 0;
- data->size = 0;
- data->free = 0;
-
- return obj;
-}
-
-/*
- * call-seq:
- * DL::CPtr.new(address) => dl_cptr
- * DL::CPtr.new(address, size) => dl_cptr
- * DL::CPtr.new(address, size, freefunc) => dl_cptr
- *
- * Create a new pointer to +address+ with an optional +size+ and +freefunc+.
- * +freefunc+ will be called when the instance is garbage collected.
- */
-static VALUE
-rb_dlptr_initialize(int argc, VALUE argv[], VALUE self)
-{
- VALUE ptr, sym, size, wrap = 0, funcwrap = 0;
- struct ptr_data *data;
- void *p = NULL;
- freefunc_t f = NULL;
- long s = 0;
-
- if (rb_scan_args(argc, argv, "12", &ptr, &size, &sym) >= 1) {
- VALUE addrnum = rb_Integer(ptr);
- if (addrnum != ptr) wrap = ptr;
- p = NUM2PTR(addrnum);
- }
- if (argc >= 2) {
- s = NUM2LONG(size);
- }
- if (argc >= 3) {
- f = get_freefunc(sym, &funcwrap);
- }
-
- if (p) {
- TypedData_Get_Struct(self, struct ptr_data, &dlptr_data_type, data);
- if (data->ptr && data->free) {
- /* Free previous memory. Use of inappropriate initialize may cause SEGV. */
- (*(data->free))(data->ptr);
- }
- data->wrap[0] = wrap;
- data->wrap[1] = funcwrap;
- data->ptr = p;
- data->size = s;
- data->free = f;
- }
-
- return Qnil;
-}
-
-/*
- * call-seq:
- *
- * Fiddle::Pointer.malloc(size, freefunc = nil) => fiddle pointer instance
- *
- * Allocate +size+ bytes of memory and associate it with an optional
- * +freefunc+ that will be called when the pointer is garbage collected.
- * +freefunc+ must be an address pointing to a function or an instance of
- * Fiddle::Function
- */
-static VALUE
-rb_dlptr_s_malloc(int argc, VALUE argv[], VALUE klass)
-{
- VALUE size, sym, obj, wrap = 0;
- long s;
- freefunc_t f;
-
- switch (rb_scan_args(argc, argv, "11", &size, &sym)) {
- case 1:
- s = NUM2LONG(size);
- f = NULL;
- break;
- case 2:
- s = NUM2LONG(size);
- f = get_freefunc(sym, &wrap);
- break;
- default:
- rb_bug("rb_dlptr_s_malloc");
- }
-
- obj = rb_dlptr_malloc(s,f);
- if (wrap) RPTR_DATA(obj)->wrap[1] = wrap;
-
- return obj;
-}
-
-/*
- * call-seq: to_i
- *
- * Returns the integer memory location of this DL::CPtr.
- */
-static VALUE
-rb_dlptr_to_i(VALUE self)
-{
- struct ptr_data *data;
-
- TypedData_Get_Struct(self, struct ptr_data, &dlptr_data_type, data);
- return PTR2NUM(data->ptr);
-}
-
-/*
- * call-seq: to_value
- *
- * Cast this CPtr to a ruby object.
- */
-static VALUE
-rb_dlptr_to_value(VALUE self)
-{
- struct ptr_data *data;
- TypedData_Get_Struct(self, struct ptr_data, &dlptr_data_type, data);
- return (VALUE)(data->ptr);
-}
-
-/*
- * call-seq: ptr
- *
- * Returns a DL::CPtr that is a dereferenced pointer for this DL::CPtr.
- * Analogous to the star operator in C.
- */
-VALUE
-rb_dlptr_ptr(VALUE self)
-{
- struct ptr_data *data;
-
- TypedData_Get_Struct(self, struct ptr_data, &dlptr_data_type, data);
- return rb_dlptr_new(*((void**)(data->ptr)),0,0);
-}
-
-/*
- * call-seq: ref
- *
- * Returns a DL::CPtr that is a reference pointer for this DL::CPtr.
- * Analogous to the ampersand operator in C.
- */
-VALUE
-rb_dlptr_ref(VALUE self)
-{
- struct ptr_data *data;
-
- TypedData_Get_Struct(self, struct ptr_data, &dlptr_data_type, data);
- return rb_dlptr_new(&(data->ptr),0,0);
-}
-
-/*
- * call-seq: null?
- *
- * Returns true if this is a null pointer.
- */
-VALUE
-rb_dlptr_null_p(VALUE self)
-{
- struct ptr_data *data;
-
- TypedData_Get_Struct(self, struct ptr_data, &dlptr_data_type, data);
- return data->ptr ? Qfalse : Qtrue;
-}
-
-/*
- * call-seq: free=(function)
- *
- * Set the free function for this pointer to the DL::CFunc in +function+.
- */
-static VALUE
-rb_dlptr_free_set(VALUE self, VALUE val)
-{
- struct ptr_data *data;
-
- TypedData_Get_Struct(self, struct ptr_data, &dlptr_data_type, data);
- data->free = get_freefunc(val, &data->wrap[1]);
-
- return Qnil;
-}
-
-/*
- * call-seq: free
- *
- * Get the free function for this pointer. Returns Fiddle::Function.
- */
-static VALUE
-rb_dlptr_free_get(VALUE self)
-{
- struct ptr_data *pdata;
- VALUE address;
- VALUE arg_types;
- VALUE ret_type;
-
- TypedData_Get_Struct(self, struct ptr_data, &dlptr_data_type, pdata);
-
- if (!pdata->free)
- return Qnil;
-
- address = PTR2NUM(pdata->free);
- ret_type = INT2NUM(TYPE_VOID);
- arg_types = rb_ary_new();
- rb_ary_push(arg_types, INT2NUM(TYPE_VOIDP));
-
- return rb_fiddle_new_function(address, arg_types, ret_type);
-}
-
-/*
- * call-seq:
- *
- * ptr.to_s => string
- * ptr.to_s(len) => string
- *
- * Returns the pointer contents as a string. When called with no arguments,
- * this method will return the contents until the first NULL byte. When
- * called with +len+, a string of +len+ bytes will be returned.
- */
-static VALUE
-rb_dlptr_to_s(int argc, VALUE argv[], VALUE self)
-{
- struct ptr_data *data;
- VALUE arg1, val;
- int len;
-
- TypedData_Get_Struct(self, struct ptr_data, &dlptr_data_type, data);
- switch (rb_scan_args(argc, argv, "01", &arg1)) {
- case 0:
- val = rb_tainted_str_new2((char*)(data->ptr));
- break;
- case 1:
- len = NUM2INT(arg1);
- val = rb_tainted_str_new((char*)(data->ptr), len);
- break;
- default:
- rb_bug("rb_dlptr_to_s");
- }
-
- return val;
-}
-
-/*
- * call-seq:
- *
- * ptr.to_str => string
- * ptr.to_str(len) => string
- *
- * Returns the pointer contents as a string. When called with no arguments,
- * this method will return the contents with the length of this pointer's
- * +size+. When called with +len+, a string of +len+ bytes will be returned.
- */
-static VALUE
-rb_dlptr_to_str(int argc, VALUE argv[], VALUE self)
-{
- struct ptr_data *data;
- VALUE arg1, val;
- int len;
-
- TypedData_Get_Struct(self, struct ptr_data, &dlptr_data_type, data);
- switch (rb_scan_args(argc, argv, "01", &arg1)) {
- case 0:
- val = rb_tainted_str_new((char*)(data->ptr),data->size);
- break;
- case 1:
- len = NUM2INT(arg1);
- val = rb_tainted_str_new((char*)(data->ptr), len);
- break;
- default:
- rb_bug("rb_dlptr_to_str");
- }
-
- return val;
-}
-
-/*
- * call-seq: inspect
- *
- * Returns a string formatted with an easily readable representation of the
- * internal state of the DL::CPtr
- */
-static VALUE
-rb_dlptr_inspect(VALUE self)
-{
- struct ptr_data *data;
- char str[1024];
-
- TypedData_Get_Struct(self, struct ptr_data, &dlptr_data_type, data);
- snprintf(str, 1023, "#<%s:%p ptr=%p size=%ld free=%p>",
- rb_class2name(CLASS_OF(self)), data, data->ptr, data->size, data->free);
- return rb_str_new2(str);
-}
-
-/*
- * call-seq:
- * ptr == other => true or false
- * ptr.eql?(other) => true or false
- *
- * Returns true if +other+ wraps the same pointer, otherwise returns
- * false.
- */
-VALUE
-rb_dlptr_eql(VALUE self, VALUE other)
-{
- void *ptr1, *ptr2;
-
- if(!rb_obj_is_kind_of(other, rb_cPointer)) return Qfalse;
-
- ptr1 = rb_dlptr2cptr(self);
- ptr2 = rb_dlptr2cptr(other);
-
- return ptr1 == ptr2 ? Qtrue : Qfalse;
-}
-
-/*
- * call-seq:
- * ptr <=> other => -1, 0, 1, or nil
- *
- * Returns -1 if less than, 0 if equal to, 1 if greater than +other+. Returns
- * nil if +ptr+ cannot be compared to +other+.
- */
-static VALUE
-rb_dlptr_cmp(VALUE self, VALUE other)
-{
- void *ptr1, *ptr2;
- SIGNED_VALUE diff;
-
- if(!rb_obj_is_kind_of(other, rb_cPointer)) return Qnil;
-
- ptr1 = rb_dlptr2cptr(self);
- ptr2 = rb_dlptr2cptr(other);
- diff = (SIGNED_VALUE)ptr1 - (SIGNED_VALUE)ptr2;
- if (!diff) return INT2FIX(0);
- return diff > 0 ? INT2NUM(1) : INT2NUM(-1);
-}
-
-/*
- * call-seq:
- * ptr + n => new cptr
- *
- * Returns a new DL::CPtr that has been advanced +n+ bytes.
- */
-static VALUE
-rb_dlptr_plus(VALUE self, VALUE other)
-{
- void *ptr;
- long num, size;
-
- ptr = rb_dlptr2cptr(self);
- size = RPTR_DATA(self)->size;
- num = NUM2LONG(other);
- return rb_dlptr_new((char *)ptr + num, size - num, 0);
-}
-
-/*
- * call-seq:
- * ptr - n => new cptr
- *
- * Returns a new DL::CPtr that has been moved back +n+ bytes.
- */
-static VALUE
-rb_dlptr_minus(VALUE self, VALUE other)
-{
- void *ptr;
- long num, size;
-
- ptr = rb_dlptr2cptr(self);
- size = RPTR_DATA(self)->size;
- num = NUM2LONG(other);
- return rb_dlptr_new((char *)ptr - num, size + num, 0);
-}
-
-/*
- * call-seq:
- * ptr[index] -> an_integer
- * ptr[start, length] -> a_string
- *
- * Returns integer stored at _index_. If _start_ and _length_ are given,
- * a string containing the bytes from _start_ of length _length_ will be
- * returned.
- */
-VALUE
-rb_dlptr_aref(int argc, VALUE argv[], VALUE self)
-{
- VALUE arg0, arg1;
- VALUE retval = Qnil;
- size_t offset, len;
- struct ptr_data *data;
-
- TypedData_Get_Struct(self, struct ptr_data, &dlptr_data_type, data);
- if (!data->ptr) rb_raise(rb_eFiddleError, "NULL pointer dereference");
- switch( rb_scan_args(argc, argv, "11", &arg0, &arg1) ){
- case 1:
- offset = NUM2ULONG(arg0);
- retval = INT2NUM(*((char *)data->ptr + offset));
- break;
- case 2:
- offset = NUM2ULONG(arg0);
- len = NUM2ULONG(arg1);
- retval = rb_tainted_str_new((char *)data->ptr + offset, len);
- break;
- default:
- rb_bug("rb_dlptr_aref()");
- }
- return retval;
-}
-
-/*
- * call-seq:
- * ptr[index] = int -> int
- * ptr[start, length] = string or cptr or addr -> string or dl_cptr or addr
- *
- * Set the value at +index+ to +int+. Or, set the memory at +start+ until
- * +length+ with the contents of +string+, the memory from +dl_cptr+, or the
- * memory pointed at by the memory address +addr+.
- */
-VALUE
-rb_dlptr_aset(int argc, VALUE argv[], VALUE self)
-{
- VALUE arg0, arg1, arg2;
- VALUE retval = Qnil;
- size_t offset, len;
- void *mem;
- struct ptr_data *data;
-
- TypedData_Get_Struct(self, struct ptr_data, &dlptr_data_type, data);
- if (!data->ptr) rb_raise(rb_eFiddleError, "NULL pointer dereference");
- switch( rb_scan_args(argc, argv, "21", &arg0, &arg1, &arg2) ){
- case 2:
- offset = NUM2ULONG(arg0);
- ((char*)data->ptr)[offset] = NUM2UINT(arg1);
- retval = arg1;
- break;
- case 3:
- offset = NUM2ULONG(arg0);
- len = NUM2ULONG(arg1);
- if (RB_TYPE_P(arg2, T_STRING)) {
- mem = StringValuePtr(arg2);
- }
- else if( rb_obj_is_kind_of(arg2, rb_cPointer) ){
- mem = rb_dlptr2cptr(arg2);
- }
- else{
- mem = NUM2PTR(arg2);
- }
- memcpy((char *)data->ptr + offset, mem, len);
- retval = arg2;
- break;
- default:
- rb_bug("rb_dlptr_aset()");
- }
- return retval;
-}
-
-/*
- * call-seq: size=(size)
- *
- * Set the size of this pointer to +size+
- */
-static VALUE
-rb_dlptr_size_set(VALUE self, VALUE size)
-{
- RPTR_DATA(self)->size = NUM2LONG(size);
- return size;
-}
-
-/*
- * call-seq: size
- *
- * Get the size of this pointer.
- */
-static VALUE
-rb_dlptr_size_get(VALUE self)
-{
- return LONG2NUM(RPTR_DATA(self)->size);
-}
-
-/*
- * call-seq:
- * Fiddle::Pointer.to_ptr(val) => cptr
- * Fiddle::Pointer[val] => cptr
- *
- * Get the underlying pointer for ruby object +val+ and return it as a
- * Fiddle::Pointer object.
- */
-static VALUE
-rb_dlptr_s_to_ptr(VALUE self, VALUE val)
-{
- VALUE ptr, wrap = val, vptr;
-
- if (RTEST(rb_obj_is_kind_of(val, rb_cIO))){
- rb_io_t *fptr;
- FILE *fp;
- GetOpenFile(val, fptr);
- fp = rb_io_stdio_file(fptr);
- ptr = rb_dlptr_new(fp, 0, NULL);
- }
- else if (RTEST(rb_obj_is_kind_of(val, rb_cString))){
- char *str = StringValuePtr(val);
- ptr = rb_dlptr_new(str, RSTRING_LEN(val), NULL);
- }
- else if ((vptr = rb_check_funcall(val, id_to_ptr, 0, 0)) != Qundef){
- if (rb_obj_is_kind_of(vptr, rb_cPointer)){
- ptr = vptr;
- wrap = 0;
- }
- else{
- rb_raise(rb_eFiddleError, "to_ptr should return a Fiddle::Pointer object");
- }
- }
- else{
- VALUE num = rb_Integer(val);
- if (num == val) wrap = 0;
- ptr = rb_dlptr_new(NUM2PTR(num), 0, NULL);
- }
- OBJ_INFECT(ptr, val);
- if (wrap) RPTR_DATA(ptr)->wrap[0] = wrap;
- return ptr;
-}
-
-void
-Init_fiddle_pointer(void)
-{
- id_to_ptr = rb_intern("to_ptr");
-
- /* Document-class: Fiddle::Pointer
- *
- * Fiddle::Pointer is a class to handle C pointers
- *
- */
- rb_cPointer = rb_define_class_under(mFiddle, "Pointer", rb_cObject);
- rb_define_alloc_func(rb_cPointer, rb_dlptr_s_allocate);
- rb_define_singleton_method(rb_cPointer, "malloc", rb_dlptr_s_malloc, -1);
- rb_define_singleton_method(rb_cPointer, "to_ptr", rb_dlptr_s_to_ptr, 1);
- rb_define_singleton_method(rb_cPointer, "[]", rb_dlptr_s_to_ptr, 1);
- rb_define_method(rb_cPointer, "initialize", rb_dlptr_initialize, -1);
- rb_define_method(rb_cPointer, "free=", rb_dlptr_free_set, 1);
- rb_define_method(rb_cPointer, "free", rb_dlptr_free_get, 0);
- rb_define_method(rb_cPointer, "to_i", rb_dlptr_to_i, 0);
- rb_define_method(rb_cPointer, "to_int", rb_dlptr_to_i, 0);
- rb_define_method(rb_cPointer, "to_value", rb_dlptr_to_value, 0);
- rb_define_method(rb_cPointer, "ptr", rb_dlptr_ptr, 0);
- rb_define_method(rb_cPointer, "+@", rb_dlptr_ptr, 0);
- rb_define_method(rb_cPointer, "ref", rb_dlptr_ref, 0);
- rb_define_method(rb_cPointer, "-@", rb_dlptr_ref, 0);
- rb_define_method(rb_cPointer, "null?", rb_dlptr_null_p, 0);
- rb_define_method(rb_cPointer, "to_s", rb_dlptr_to_s, -1);
- rb_define_method(rb_cPointer, "to_str", rb_dlptr_to_str, -1);
- rb_define_method(rb_cPointer, "inspect", rb_dlptr_inspect, 0);
- rb_define_method(rb_cPointer, "<=>", rb_dlptr_cmp, 1);
- rb_define_method(rb_cPointer, "==", rb_dlptr_eql, 1);
- rb_define_method(rb_cPointer, "eql?", rb_dlptr_eql, 1);
- rb_define_method(rb_cPointer, "+", rb_dlptr_plus, 1);
- rb_define_method(rb_cPointer, "-", rb_dlptr_minus, 1);
- rb_define_method(rb_cPointer, "[]", rb_dlptr_aref, -1);
- rb_define_method(rb_cPointer, "[]=", rb_dlptr_aset, -1);
- rb_define_method(rb_cPointer, "size", rb_dlptr_size_get, 0);
- rb_define_method(rb_cPointer, "size=", rb_dlptr_size_set, 1);
-
- /* Document-const: NULL
- *
- * A NULL pointer
- */
- rb_define_const(mFiddle, "NULL", rb_dlptr_new(0, 0, 0));
-}
diff --git a/test/dl/test_callback.rb b/test/dl/test_callback.rb
index 8ae652b95a..fb24ff0ca5 100644
--- a/test/dl/test_callback.rb
+++ b/test/dl/test_callback.rb
@@ -25,7 +25,7 @@ module DL
func = CFunc.new(addr, TYPE_VOIDP, 'test')
f = Function.new(func, [TYPE_VOIDP])
ptr = CPtr['blah']
- assert_equal ptr.to_i, f.call(ptr).to_i
+ assert_equal ptr, f.call(ptr)
end
def test_callback_return_arbitrary
diff --git a/test/fiddle/helper.rb b/test/fiddle/helper.rb
index 209dedb6fc..ad69f55e69 100644
--- a/test/fiddle/helper.rb
+++ b/test/fiddle/helper.rb
@@ -1,4 +1,5 @@
require 'minitest/autorun'
+require 'dl'
require 'fiddle'
# FIXME: this is stolen from DL and needs to be refactored.
@@ -103,8 +104,8 @@ Fiddle::LIBM_SO = libm_so
module Fiddle
class TestCase < MiniTest::Unit::TestCase
def setup
- @libc = Fiddle.dlopen(LIBC_SO)
- @libm = Fiddle.dlopen(LIBM_SO)
+ @libc = DL.dlopen(LIBC_SO)
+ @libm = DL.dlopen(LIBM_SO)
end
end
end
diff --git a/test/fiddle/test_closure.rb b/test/fiddle/test_closure.rb
index 56839e7b63..381b3f96c1 100644
--- a/test/fiddle/test_closure.rb
+++ b/test/fiddle/test_closure.rb
@@ -57,8 +57,8 @@ module Fiddle
end
%w[INT SHORT CHAR LONG LONG_LONG].each do |name|
- type = Fiddle.const_get("TYPE_#{name}") rescue next
- size = Fiddle.const_get("SIZEOF_#{name}")
+ type = DL.const_get("TYPE_#{name}") rescue next
+ size = DL.const_get("SIZEOF_#{name}")
[[type, size-1, name], [-type, size, "unsigned_"+name]].each do |t, s, n|
define_method("test_conversion_#{n.downcase}") do
arg = nil
diff --git a/test/fiddle/test_fiddle.rb b/test/fiddle/test_fiddle.rb
index 4c6ab97b12..f910978af5 100644
--- a/test/fiddle/test_fiddle.rb
+++ b/test/fiddle/test_fiddle.rb
@@ -4,6 +4,27 @@ rescue LoadError
end
class TestFiddle < Fiddle::TestCase
+ def test_constants_match
+ [
+ :TYPE_VOID,
+ :TYPE_VOIDP,
+ :TYPE_CHAR,
+ :TYPE_SHORT,
+ :TYPE_INT,
+ :TYPE_LONG,
+ :TYPE_LONG_LONG,
+ :TYPE_FLOAT,
+ :TYPE_DOUBLE,
+ :TYPE_SIZE_T,
+ :TYPE_SSIZE_T,
+ :TYPE_PTRDIFF_T,
+ :TYPE_INTPTR_T,
+ :TYPE_UINTPTR_T,
+ ].each do |name|
+ assert_equal(DL.const_get(name), Fiddle.const_get(name), "Fiddle::#{name}")
+ end
+ end
+
def test_windows_constant
require 'rbconfig'
if RbConfig::CONFIG['host_os'] =~ /mswin|mingw/
diff --git a/test/fiddle/test_func.rb b/test/fiddle/test_func.rb
deleted file mode 100644
index e77229b7e8..0000000000
--- a/test/fiddle/test_func.rb
+++ /dev/null
@@ -1,79 +0,0 @@
-require_relative 'helper'
-
-module Fiddle
- class TestFunc < TestCase
- def test_random
- f = Function.new(@libc['srand'], [-TYPE_LONG], TYPE_VOID)
- assert_nil f.call(10)
- end
-
- def test_sinf
- begin
- f = Function.new(@libm['sinf'], [TYPE_FLOAT], TYPE_FLOAT)
- rescue Fiddle::DLError
- skip "libm may not have sinf()"
- end
- assert_in_delta 1.0, f.call(90 * Math::PI / 180), 0.0001
- end
-
- def test_sin
- f = Function.new(@libm['sin'], [TYPE_DOUBLE], TYPE_DOUBLE)
- assert_in_delta 1.0, f.call(90 * Math::PI / 180), 0.0001
- end
-
- def test_string
- stress, GC.stress = GC.stress, true
- f = Function.new(@libc['strcpy'], [TYPE_VOIDP, TYPE_VOIDP], TYPE_VOIDP)
- buff = "000"
- str = f.call(buff, "123")
- assert_equal("123", buff)
- assert_equal("123", str.to_s)
- ensure
- GC.stress = stress
- end
-
- def test_isdigit
- f = Function.new(@libc['isdigit'], [TYPE_INT], TYPE_INT)
- r1 = f.call(?1.ord)
- r2 = f.call(?2.ord)
- rr = f.call(?r.ord)
- assert_operator r1, :>, 0
- assert_operator r2, :>, 0
- assert_equal 0, rr
- end
-
- def test_atof
- f = Function.new(@libc['atof'], [TYPE_VOIDP], TYPE_DOUBLE)
- r = f.call("12.34")
- assert_includes(12.00..13.00, r)
- end
-
- def test_strtod
- f = Function.new(@libc['strtod'], [TYPE_VOIDP, TYPE_VOIDP], TYPE_DOUBLE)
- buff1 = Pointer["12.34"]
- buff2 = buff1 + 4
- r = f.call(buff1, - buff2)
- assert_in_delta(12.34, r, 0.001)
- end
-
- def test_qsort1
- cb = Class.new(Closure) {
- def call(x, y)
- Pointer.new(x)[0] <=> Pointer.new(y)[0]
- end
- }.new(TYPE_INT, [TYPE_VOIDP, TYPE_VOIDP])
-
- qsort = Function.new(@libc['qsort'],
- [TYPE_VOIDP, TYPE_SIZE_T, TYPE_SIZE_T, TYPE_VOIDP],
- TYPE_VOID)
- buff = "9341"
- qsort.call(buff, buff.size, 1, cb)
- assert_equal("1349", buff)
-
- bug4929 = '[ruby-core:37395]'
- buff = "9341"
- EnvUtil.under_gc_stress {qsort.call(buff, buff.size, 1, cb)}
- assert_equal("1349", buff, bug4929)
- end
- end
-end
diff --git a/test/fiddle/test_handle.rb b/test/fiddle/test_handle.rb
deleted file mode 100644
index f11272abbf..0000000000
--- a/test/fiddle/test_handle.rb
+++ /dev/null
@@ -1,186 +0,0 @@
-require_relative 'helper'
-
-module Fiddle
- class TestHandle < TestCase
- include Fiddle
-
- def test_to_i
- handle = Fiddle::Handle.new(LIBC_SO)
- assert_kind_of Integer, handle.to_i
- end
-
- def test_static_sym_secure
- assert_raises(SecurityError) do
- Thread.new do
- $SAFE = 2
- Fiddle::Handle.sym('calloc')
- end.join
- end
- end
-
- def test_static_sym_unknown
- assert_raises(DLError) { Fiddle::Handle.sym('fooo') }
- assert_raises(DLError) { Fiddle::Handle['fooo'] }
- end
-
- def test_static_sym
- skip "Fiddle::Handle.sym is not supported" if /mswin|mingw/ =~ RUBY_PLATFORM
- begin
- # Linux / Darwin / FreeBSD
- refute_nil Fiddle::Handle.sym('dlopen')
- assert_equal Fiddle::Handle.sym('dlopen'), Fiddle::Handle['dlopen']
- rescue
- # NetBSD
- require 'objspace'
- refute_nil Fiddle::Handle.sym('Init_objspace')
- assert_equal Fiddle::Handle.sym('Init_objspace'), Fiddle::Handle['Init_objspace']
- end
- end
-
- def test_sym_closed_handle
- handle = Fiddle::Handle.new(LIBC_SO)
- handle.close
- assert_raises(DLError) { handle.sym("calloc") }
- assert_raises(DLError) { handle["calloc"] }
- end
-
- def test_sym_unknown
- handle = Fiddle::Handle.new(LIBC_SO)
- assert_raises(DLError) { handle.sym('fooo') }
- assert_raises(DLError) { handle['fooo'] }
- end
-
- def test_sym_with_bad_args
- handle = Handle.new(LIBC_SO)
- assert_raises(TypeError) { handle.sym(nil) }
- assert_raises(TypeError) { handle[nil] }
- end
-
- def test_sym_secure
- assert_raises(SecurityError) do
- Thread.new do
- $SAFE = 2
- handle = Handle.new(LIBC_SO)
- handle.sym('calloc')
- end.join
- end
- end
-
- def test_sym
- handle = Handle.new(LIBC_SO)
- refute_nil handle.sym('calloc')
- refute_nil handle['calloc']
- end
-
- def test_handle_close
- handle = Handle.new(LIBC_SO)
- assert_equal 0, handle.close
- end
-
- def test_handle_close_twice
- handle = Handle.new(LIBC_SO)
- handle.close
- assert_raises(DLError) do
- handle.close
- end
- end
-
- def test_dlopen_returns_handle
- assert_instance_of Handle, dlopen(LIBC_SO)
- end
-
- def test_dlopen_safe
- assert_raises(SecurityError) do
- Thread.new do
- $SAFE = 2
- dlopen(LIBC_SO)
- end.join
- end
- end
-
- def test_initialize_safe
- assert_raises(SecurityError) do
- Thread.new do
- $SAFE = 2
- Handle.new(LIBC_SO)
- end.join
- end
- end
-
- def test_initialize_noargs
- handle = Handle.new
- refute_nil handle['rb_str_new']
- end
-
- def test_initialize_flags
- handle = Handle.new(LIBC_SO, RTLD_LAZY | RTLD_GLOBAL)
- refute_nil handle['calloc']
- end
-
- def test_enable_close
- handle = Handle.new(LIBC_SO)
- assert !handle.close_enabled?, 'close is enabled'
-
- handle.enable_close
- assert handle.close_enabled?, 'close is not enabled'
- end
-
- def test_disable_close
- handle = Handle.new(LIBC_SO)
-
- handle.enable_close
- assert handle.close_enabled?, 'close is enabled'
- handle.disable_close
- assert !handle.close_enabled?, 'close is enabled'
- end
-
- def test_NEXT
- begin
- # Linux / Darwin
- #
- # There are two special pseudo-handles, RTLD_DEFAULT and RTLD_NEXT. The former will find
- # the first occurrence of the desired symbol using the default library search order. The
- # latter will find the next occurrence of a function in the search order after the current
- # library. This allows one to provide a wrapper around a function in another shared
- # library.
- # --- Ubuntu Linux 8.04 dlsym(3)
- handle = Handle::NEXT
- refute_nil handle['malloc']
- rescue
- # BSD
- #
- # If dlsym() is called with the special handle RTLD_NEXT, then the search
- # for the symbol is limited to the shared objects which were loaded after
- # the one issuing the call to dlsym(). Thus, if the function is called
- # from the main program, all the shared libraries are searched. If it is
- # called from a shared library, all subsequent shared libraries are
- # searched. RTLD_NEXT is useful for implementing wrappers around library
- # functions. For example, a wrapper function getpid() could access the
- # "real" getpid() with dlsym(RTLD_NEXT, "getpid"). (Actually, the dlfunc()
- # interface, below, should be used, since getpid() is a function and not a
- # data object.)
- # --- FreeBSD 8.0 dlsym(3)
- require 'objspace'
- handle = Handle::NEXT
- refute_nil handle['Init_objspace']
- end
- end unless /mswin|mingw/ =~ RUBY_PLATFORM
-
- def test_DEFAULT
- skip "Handle::DEFAULT is not supported" if /mswin|mingw/ =~ RUBY_PLATFORM
- handle = Handle::DEFAULT
- refute_nil handle['malloc']
- end unless /mswin|mingw/ =~ RUBY_PLATFORM
-
- def test_dlerror
- # FreeBSD (at least 7.2 to 7.2) calls nsdispatch(3) when it calls
- # getaddrinfo(3). And nsdispatch(3) doesn't call dlerror(3) even if
- # it calls _nss_cache_cycle_prevention_function with dlsym(3).
- # So our Fiddle::Handle#sym must call dlerror(3) before call dlsym.
- # In general uses of dlerror(3) should call it before use it.
- require 'socket'
- Socket.gethostbyname("localhost")
- Fiddle.dlopen("/usr/lib/libc.so").sym('strcpy')
- end if /freebsd/=~ RUBY_PLATFORM
- end
-end
diff --git a/test/fiddle/test_pointer.rb b/test/fiddle/test_pointer.rb
deleted file mode 100644
index ef33b91062..0000000000
--- a/test/fiddle/test_pointer.rb
+++ /dev/null
@@ -1,231 +0,0 @@
-require_relative 'helper'
-require_relative '../ruby/envutil'
-
-module Fiddle
- class TestPointer < TestCase
- def dlwrap arg
- Fiddle.dlwrap arg
- end
-
- include Test::Unit::Assertions
-
- def test_cptr_to_int
- null = Fiddle::NULL
- assert_equal(null.to_i, null.to_int)
- end
-
- def test_malloc_free_func_int
- free = Fiddle::Function.new(Fiddle::RUBY_FREE, [TYPE_VOIDP], TYPE_VOID)
- assert_equal free.to_i, Fiddle::RUBY_FREE.to_i
-
- ptr = Pointer.malloc(10, free.to_i)
- assert_equal 10, ptr.size
- assert_equal free.to_i, ptr.free.to_i
- end
-
- def test_malloc_free_func
- free = Fiddle::Function.new(Fiddle::RUBY_FREE, [TYPE_VOIDP], TYPE_VOID)
-
- ptr = Pointer.malloc(10, free)
- assert_equal 10, ptr.size
- assert_equal free.to_i, ptr.free.to_i
- end
-
- def test_to_str
- str = "hello world"
- ptr = Pointer[str]
-
- assert_equal 3, ptr.to_str(3).length
- assert_equal str, ptr.to_str
-
- ptr[5] = 0
- assert_equal "hello\0world", ptr.to_str
- end
-
- def test_to_s
- str = "hello world"
- ptr = Pointer[str]
-
- assert_equal 3, ptr.to_s(3).length
- assert_equal str, ptr.to_s
-
- ptr[5] = 0
- assert_equal 'hello', ptr.to_s
- end
-
- def test_minus
- str = "hello world"
- ptr = Pointer[str]
- assert_equal ptr.to_s, (ptr + 3 - 3).to_s
- end
-
- # TODO: what if the pointer size is 0? raise an exception? do we care?
- def test_plus
- str = "hello world"
- ptr = Pointer[str]
- new_str = ptr + 3
- assert_equal 'lo world', new_str.to_s
- end
-
- def test_inspect
- ptr = Pointer.new(0)
- inspect = ptr.inspect
- assert_match(/size=#{ptr.size}/, inspect)
- assert_match(/free=#{sprintf("%#x", ptr.free.to_i)}/, inspect)
- assert_match(/ptr=#{sprintf("%#x", ptr.to_i)}/, inspect)
- end
-
- def test_to_ptr_string
- str = "hello world"
- ptr = Pointer[str]
- assert ptr.tainted?, 'pointer should be tainted'
- assert_equal str.length, ptr.size
- assert_equal 'hello', ptr[0,5]
- end
-
- def test_to_ptr_io
- buf = Pointer.malloc(10)
- File.open(__FILE__, 'r') do |f|
- ptr = Pointer.to_ptr f
- fread = Function.new(@libc['fread'],
- [TYPE_VOIDP, TYPE_INT, TYPE_INT, TYPE_VOIDP],
- TYPE_INT)
- fread.call(buf.to_i, Fiddle::SIZEOF_CHAR, buf.size - 1, ptr.to_i)
- end
-
- File.open(__FILE__, 'r') do |f|
- assert_equal f.read(9), buf.to_s
- end
- end
-
- def test_to_ptr_with_ptr
- ptr = Pointer.new 0
- ptr2 = Pointer.to_ptr Struct.new(:to_ptr).new(ptr)
- assert_equal ptr, ptr2
-
- assert_raises(Fiddle::DLError) do
- Pointer.to_ptr Struct.new(:to_ptr).new(nil)
- end
- end
-
- def test_to_ptr_with_num
- ptr = Pointer.new 0
- assert_equal ptr, Pointer[0]
- end
-
- def test_equals
- ptr = Pointer.new 0
- ptr2 = Pointer.new 0
- assert_equal ptr2, ptr
- end
-
- def test_not_equals
- ptr = Pointer.new 0
- refute_equal 10, ptr, '10 should not equal the pointer'
- end
-
- def test_cmp
- ptr = Pointer.new 0
- assert_nil(ptr <=> 10, '10 should not be comparable')
- end
-
- def test_ref_ptr
- ary = [0,1,2,4,5]
- addr = Pointer.new(dlwrap(ary))
- assert_equal addr.to_i, addr.ref.ptr.to_i
-
- assert_equal addr.to_i, (+ (- addr)).to_i
- end
-
- def test_to_value
- ary = [0,1,2,4,5]
- addr = Pointer.new(dlwrap(ary))
- assert_equal ary, addr.to_value
- end
-
- def test_free
- ptr = Pointer.malloc(4)
- assert_nil ptr.free
- end
-
- def test_free=
- assert_normal_exit(<<-"End", '[ruby-dev:39269]')
- require 'fiddle'
- Fiddle::LIBC_SO = #{Fiddle::LIBC_SO.dump}
- Fiddle::LIBM_SO = #{Fiddle::LIBM_SO.dump}
- include Fiddle
- @libc = dlopen(LIBC_SO)
- @libm = dlopen(LIBM_SO)
- free = Fiddle::Function.new(Fiddle::RUBY_FREE, [TYPE_VOIDP], TYPE_VOID)
- ptr = Fiddle::Pointer.malloc(4)
- ptr.free = free
- free.ptr
- ptr.free.ptr
- End
-
- free = Function.new(Fiddle::RUBY_FREE, [TYPE_VOIDP], TYPE_VOID)
- ptr = Pointer.malloc(4)
- ptr.free = free
-
- assert_equal free.ptr, ptr.free.ptr
- end
-
- def test_null?
- ptr = Pointer.new(0)
- assert ptr.null?
- end
-
- def test_size
- ptr = Pointer.malloc(4)
- assert_equal 4, ptr.size
- Fiddle.free ptr.to_i
- end
-
- def test_size=
- ptr = Pointer.malloc(4)
- ptr.size = 10
- assert_equal 10, ptr.size
- Fiddle.free ptr.to_i
- end
-
- def test_aref_aset
- check = Proc.new{|str,ptr|
- assert_equal(str.size(), ptr.size())
- assert_equal(str, ptr.to_s())
- assert_equal(str[0,2], ptr.to_s(2))
- assert_equal(str[0,2], ptr[0,2])
- assert_equal(str[1,2], ptr[1,2])
- assert_equal(str[1,0], ptr[1,0])
- assert_equal(str[0].ord, ptr[0])
- assert_equal(str[1].ord, ptr[1])
- }
- str = 'abc'
- ptr = Pointer[str]
- check.call(str, ptr)
-
- str[0] = "c"
- assert_equal 'c'.ord, ptr[0] = "c".ord
- check.call(str, ptr)
-
- str[0,2] = "aa"
- assert_equal 'aa', ptr[0,2] = "aa"
- check.call(str, ptr)
-
- ptr2 = Pointer['cdeeee']
- str[0,2] = "cd"
- assert_equal ptr2, ptr[0,2] = ptr2
- check.call(str, ptr)
-
- ptr3 = Pointer['vvvv']
- str[0,2] = "vv"
- assert_equal ptr3.to_i, ptr[0,2] = ptr3.to_i
- check.call(str, ptr)
- end
-
- def test_null_pointer
- nullpo = Pointer.new(0)
- assert_raise(DLError) {nullpo[0]}
- assert_raise(DLError) {nullpo[0] = 1}
- end
- end
-end