11 dlhandle_free(struct dl_handle
*dlhandle
)
13 if( dlhandle
->ptr
&& dlhandle
->open
&& dlhandle
->enable_close
){
14 dlclose(dlhandle
->ptr
);
19 rb_dlhandle_close(VALUE self
)
21 struct dl_handle
*dlhandle
;
23 Data_Get_Struct(self
, struct dl_handle
, dlhandle
);
25 return INT2NUM(dlclose(dlhandle
->ptr
));
29 rb_dlhandle_s_allocate(VALUE klass
)
32 struct dl_handle
*dlhandle
;
34 obj
= Data_Make_Struct(rb_cDLHandle
, struct dl_handle
, 0,
35 dlhandle_free
, dlhandle
);
38 dlhandle
->enable_close
= 0;
44 rb_dlhandle_initialize(int argc
, VALUE argv
[], VALUE self
)
47 struct dl_handle
*dlhandle
;
53 switch( rb_scan_args(argc
, argv
, "02", &lib
, &flag
) ){
56 cflag
= RTLD_LAZY
| RTLD_GLOBAL
;
59 clib
= NIL_P(lib
) ? NULL
: StringValuePtr(lib
);
60 cflag
= RTLD_LAZY
| RTLD_GLOBAL
;
63 clib
= NIL_P(lib
) ? NULL
: StringValuePtr(lib
);
64 cflag
= NUM2INT(flag
);
67 rb_bug("rb_dlhandle_new");
70 ptr
= dlopen(clib
, cflag
);
71 #if defined(HAVE_DLERROR)
72 if( !ptr
&& (err
= dlerror()) ){
73 rb_raise(rb_eDLError
, "%s", err
);
78 rb_raise(rb_eDLError
, "%s", err
);
81 Data_Get_Struct(self
, struct dl_handle
, dlhandle
);
82 if( dlhandle
->ptr
&& dlhandle
->open
&& dlhandle
->enable_close
){
83 dlclose(dlhandle
->ptr
);
87 dlhandle
->enable_close
= 0;
89 if( rb_block_given_p() ){
90 rb_ensure(rb_yield
, self
, rb_dlhandle_close
, self
);
97 rb_dlhandle_enable_close(VALUE self
)
99 struct dl_handle
*dlhandle
;
101 Data_Get_Struct(self
, struct dl_handle
, dlhandle
);
102 dlhandle
->enable_close
= 1;
107 rb_dlhandle_disable_close(VALUE self
)
109 struct dl_handle
*dlhandle
;
111 Data_Get_Struct(self
, struct dl_handle
, dlhandle
);
112 dlhandle
->enable_close
= 0;
117 rb_dlhandle_to_i(VALUE self
)
119 struct dl_handle
*dlhandle
;
121 Data_Get_Struct(self
, struct dl_handle
, dlhandle
);
122 return PTR2NUM(dlhandle
);
126 rb_dlhandle_sym(VALUE self
, VALUE sym
)
129 struct dl_handle
*dlhandle
;
135 #if defined(HAVE_DLERROR)
136 # define CHECK_DLERROR if( err = dlerror() ){ func = 0; }
138 # define CHECK_DLERROR
144 #if defined(RTLD_NEXT)
151 name
= StringValuePtr(sym
);
155 Data_Get_Struct(self
, struct dl_handle
, dlhandle
);
156 if( ! dlhandle
->open
){
157 rb_raise(rb_eDLError
, "closed handle");
159 handle
= dlhandle
->ptr
;
161 func
= dlsym(handle
, name
);
164 #if defined(__CYGWIN__) || defined(WIN32) || defined(__MINGW32__)
166 int len
= strlen(name
);
167 char *name_a
= (char*)xmalloc(len
+2);
168 strcpy(name_a
, name
);
170 name_a
[len
+1] = '\0';
171 func
= dlsym(handle
, name_a
);
175 for( i
= 0; i
< 256; i
+= 4 ){
176 int len
= strlen(name
);
177 char *name_n
= (char*)xmalloc(len
+5);
178 sprintf(name_n
, "%s@%d%c", name
, i
, 0);
179 func
= dlsym(handle
, name_n
);
189 rb_raise(rb_eDLError
, "unknown symbol \"%s\"", name
);
194 for( i
= 0; i
< 256; i
+= 4 ){
195 int len
= strlen(name
);
196 char *name_n
= (char*)xmalloc(len
+4);
197 sprintf(name_n
, "%s@%d", name
, i
);
198 func
= dlsym(handle
, name_n
);
207 rb_raise(rb_eDLError
, "unknown symbol \"%s\"", name
);
212 return PTR2NUM(func
);
218 rb_cDLHandle
= rb_define_class_under(rb_mDL
, "Handle", rb_cObject
);
219 rb_define_alloc_func(rb_cDLHandle
, rb_dlhandle_s_allocate
);
220 rb_define_method(rb_cDLHandle
, "initialize", rb_dlhandle_initialize
, -1);
221 rb_define_method(rb_cDLHandle
, "to_i", rb_dlhandle_to_i
, 0);
222 rb_define_method(rb_cDLHandle
, "close", rb_dlhandle_close
, 0);
223 rb_define_method(rb_cDLHandle
, "sym", rb_dlhandle_sym
, 1);
224 rb_define_method(rb_cDLHandle
, "[]", rb_dlhandle_sym
, 1);
225 rb_define_method(rb_cDLHandle
, "disable_close", rb_dlhandle_disable_close
, 0);
226 rb_define_method(rb_cDLHandle
, "enable_close", rb_dlhandle_enable_close
, 0);