summaryrefslogtreecommitdiff
path: root/ext/dl
diff options
context:
space:
mode:
authorttate <ttate@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2003-11-08 04:48:35 +0000
committerttate <ttate@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2003-11-08 04:48:35 +0000
commit0f8d55fa98c37fb2b0925620c10fd305f63acd84 (patch)
tree29ee85a295913f4a3311225b21dadc7a0492feb4 /ext/dl
parent3d337f360679bed00aafc40d77181016f902e862 (diff)
Add DL.win32_last_error and DL.last_error.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@4922 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'ext/dl')
-rw-r--r--ext/dl/extconf.rb10
-rw-r--r--ext/dl/sym.c61
2 files changed, 69 insertions, 2 deletions
diff --git a/ext/dl/extconf.rb b/ext/dl/extconf.rb
index e712134448..beb15ab04c 100644
--- a/ext/dl/extconf.rb
+++ b/ext/dl/extconf.rb
@@ -127,6 +127,13 @@ if( $with_type_voidp )
$dlconfig_h << "#define WITH_TYPE_VOIDP\n"
end
+if( have_header("windows.h") )
+ have_library("kernel32")
+ have_func("GetLastError", "windows.h")
+ dlc_define("HAVE_WINDOWS_H")
+ have_windows_h = true
+end
+
if( have_header("dlfcn.h") )
dlc_define("HAVE_DLFCN_H")
have_library("dl")
@@ -136,8 +143,7 @@ if( have_header("dlfcn.h") )
if( have_func("dlerror") )
dlc_define("HAVE_DLERROR")
end
-elsif( have_header("windows.h") )
- dlc_define("HAVE_WINDOWS_H")
+elsif ( have_windows_h )
have_func("LoadLibrary")
have_func("FreeLibrary")
have_func("GetProcAddress")
diff --git a/ext/dl/sym.c b/ext/dl/sym.c
index 4a2d736465..dc48f6ce95 100644
--- a/ext/dl/sym.c
+++ b/ext/dl/sym.c
@@ -3,6 +3,7 @@
*/
#include <ruby.h>
+#include <errno.h>
#include "dl.h"
VALUE rb_cDLSymbol;
@@ -316,6 +317,41 @@ stack_size(struct sym_data *sym)
return size;
}
+static ID rb_dl_id_DLErrno;
+
+static VALUE
+rb_dl_get_last_error(VALUE self)
+{
+ return rb_thread_local_aref(rb_thread_current(), rb_dl_id_DLErrno);
+}
+
+static VALUE
+rb_dl_set_last_error(VALUE self, VALUE val)
+{
+ errno = NUM2INT(val);
+ rb_thread_local_aset(rb_thread_current(), rb_dl_id_DLErrno, val);
+ return Qnil;
+}
+
+#ifdef HAVE_WINDOWS_H
+#include <windows.h>
+static ID rb_dl_id_DLW32Error;
+
+static VALUE
+rb_dl_win32_get_lasterror(VALUE self)
+{
+ return rb_thread_local_aref(rb_thread_current(), rb_dl_id_DLW32Error);
+}
+
+static VALUE
+rb_dl_win32_set_lasterror(VALUE self, VALUE val)
+{
+ SetLastError(NUM2INT(val));
+ rb_thread_local_aset(rb_thread_current(), rb_dl_id_DLW32Error, val);
+ return Qnil;
+}
+#endif
+
VALUE
rb_dlsym_call(int argc, VALUE argv[], VALUE self)
{
@@ -675,6 +711,22 @@ rb_dlsym_call(int argc, VALUE argv[], VALUE self)
rb_raise(rb_eDLTypeError, "unknown type `%c'", sym->type[0]);
}
}
+
+ {
+ /*
+ * We should get the value of errno/GetLastError() before calling another functions.
+ */
+ int last_errno = errno;
+#ifdef _WIN32
+ DWORD win32_last_err = GetLastError();
+#endif
+
+ rb_thread_local_aset(rb_thread_current(), rb_dl_id_DLErrno, INT2NUM(last_errno));
+#ifdef _WIN32
+ rb_thread_local_aset(rb_thread_current(), rb_dl_id_DLW32Error, INT2NUM(win32_last_err));
+#endif
+ }
+
}
#else /* defined(DLSTACK) */
switch(ftype){
@@ -835,4 +887,13 @@ Init_dlsym()
rb_define_method(rb_cDLSymbol, "to_s", rb_dlsym_cproto, 0);
rb_define_method(rb_cDLSymbol, "to_ptr", rb_dlsym_to_ptr, 0);
rb_define_method(rb_cDLSymbol, "to_i", rb_dlsym_to_i, 0);
+
+ rb_dl_id_DLErrno = rb_intern("DLErrno");
+ rb_define_singleton_method(rb_mDL, "last_error", rb_dl_get_last_error, 0);
+ rb_define_singleton_method(rb_mDL, "last_error=", rb_dl_set_last_error, 1);
+#ifdef _WIN32
+ rb_dl_id_DLW32Error = rb_intern("DLW32Error");
+ rb_define_singleton_method(rb_mDL, "win32_last_error", rb_dl_win32_get_last_error, 0);
+ rb_define_singleton_method(rb_mDL, "win32_last_error=", rb_dl_win32_set_last_error, 1);
+#endif
}