DEFINITIONS
This source file includes following functions.
- dlhandle_free
- rb_dlhandle_close
- rb_dlhandle_s_allocate
- rb_dlhandle_initialize
- rb_dlhandle_enable_close
- rb_dlhandle_disable_close
- rb_dlhandle_to_i
- rb_dlhandle_to_ptr
- rb_dlhandle_sym
- Init_dlhandle
1
2
3
4
5 #include <ruby.h>
6 #include "dl.h"
7
8 VALUE rb_cDLHandle;
9
10 void
11 dlhandle_free(struct dl_handle *dlhandle)
12 {
13 if( dlhandle->ptr && dlhandle->open && dlhandle->enable_close ){
14 dlclose(dlhandle->ptr);
15 };
16 }
17
18 VALUE
19 rb_dlhandle_close(VALUE self)
20 {
21 struct dl_handle *dlhandle;
22
23 Data_Get_Struct(self, struct dl_handle, dlhandle);
24 dlhandle->open = 0;
25 return INT2NUM(dlclose(dlhandle->ptr));
26 }
27
28 VALUE
29 rb_dlhandle_s_allocate(VALUE klass)
30 {
31 VALUE obj;
32 struct dl_handle *dlhandle;
33
34 obj = Data_Make_Struct(rb_cDLHandle, struct dl_handle, 0,
35 dlhandle_free, dlhandle);
36 dlhandle->ptr = 0;
37 dlhandle->open = 0;
38 dlhandle->enable_close = 0;
39
40 return obj;
41 }
42
43 VALUE
44 rb_dlhandle_initialize(int argc, VALUE argv[], VALUE self)
45 {
46 void *ptr;
47 struct dl_handle *dlhandle;
48 VALUE lib, flag;
49 char *clib;
50 int cflag;
51 const char *err;
52
53 switch( rb_scan_args(argc, argv, "11", &lib, &flag) ){
54 case 1:
55 clib = StringValuePtr(lib);
56 cflag = RTLD_LAZY | RTLD_GLOBAL;
57 break;
58 case 2:
59 clib = StringValuePtr(lib);
60 cflag = NUM2INT(flag);
61 break;
62 default:
63 rb_bug("rb_dlhandle_new");
64 };
65
66 ptr = dlopen(clib, cflag);
67 #if defined(HAVE_DLERROR)
68 if( (err = dlerror()) ){
69 rb_raise(rb_eRuntimeError, err);
70 };
71 #else
72 if( !ptr ){
73 err = dlerror();
74 rb_raise(rb_eRuntimeError, err);
75 };
76 #endif
77 Data_Get_Struct(self, struct dl_handle, dlhandle);
78 if( dlhandle->ptr && dlhandle->open && dlhandle->enable_close ){
79 dlclose(dlhandle->ptr);
80 }
81 dlhandle->ptr = ptr;
82 dlhandle->open = 1;
83 dlhandle->enable_close = 0;
84
85 if( rb_block_given_p() ){
86 rb_ensure(rb_yield, self, rb_dlhandle_close, self);
87 };
88
89 return Qnil;
90 }
91
92 VALUE
93 rb_dlhandle_enable_close(VALUE self)
94 {
95 struct dl_handle *dlhandle;
96
97 Data_Get_Struct(self, struct dl_handle, dlhandle);
98 dlhandle->enable_close = 1;
99 return Qnil;
100 }
101
102 VALUE
103 rb_dlhandle_disable_close(VALUE self)
104 {
105 struct dl_handle *dlhandle;
106
107 Data_Get_Struct(self, struct dl_handle, dlhandle);
108 dlhandle->enable_close = 0;
109 return Qnil;
110 }
111
112 VALUE
113 rb_dlhandle_to_i(VALUE self)
114 {
115 struct dl_handle *dlhandle;
116
117 Data_Get_Struct(self, struct dl_handle, dlhandle);
118 return DLLONG2NUM(dlhandle);
119 }
120
121 VALUE
122 rb_dlhandle_to_ptr(VALUE self)
123 {
124 struct dl_handle *dlhandle;
125
126 Data_Get_Struct(self, struct dl_handle, dlhandle);
127 return rb_dlptr_new(dlhandle, sizeof(dlhandle), 0);
128 }
129
130 VALUE
131 rb_dlhandle_sym(int argc, VALUE argv[], VALUE self)
132 {
133 VALUE sym, type;
134 void (*func)();
135 VALUE val;
136 struct sym_data *data;
137 int *ctypes;
138 int i, ctypes_len;
139 struct dl_handle *dlhandle;
140 void *handle;
141 const char *name, *stype;
142 const char *err;
143
144 if( rb_scan_args(argc, argv, "11", &sym, &type) == 2 ){
145 stype = StringValuePtr(type);
146 }
147 else{
148 stype = NULL;
149 };
150
151 if( sym == Qnil ){
152 #if defined(RTLD_NEXT)
153 name = RTLD_NEXT;
154 #else
155 name = NULL;
156 #endif
157 }
158 else{
159 name = StringValuePtr(sym);
160 };
161
162
163 Data_Get_Struct(self, struct dl_handle, dlhandle);
164 if( ! dlhandle->open ){
165 rb_raise(rb_eRuntimeError, "Closed handle.");
166 }
167 handle = dlhandle->ptr;
168
169 func = dlsym(handle, name);
170 #if defined(HAVE_DLERROR)
171 if( (err = dlerror()) && (!func) )
172 #else
173 if( !func )
174 #endif
175 {
176 #if defined(__CYGWIN__) || defined(WIN32) || defined(__MINGW32__)
177 {
178 int len = strlen(name);
179 char *name_a = (char*)dlmalloc(len+2);
180 strcpy(name_a, name);
181 name_a[len] = 'A';
182 name_a[len+1] = '\0';
183 func = dlsym(handle, name_a);
184 dlfree(name_a);
185 #if defined(HAVE_DLERROR)
186 if( (err = dlerror()) && (!func) )
187 #else
188 if( !func )
189 #endif
190 {
191 rb_raise(rb_eRuntimeError, "Unknown symbol \"%sA\".", name);
192 };
193 }
194 #else
195 rb_raise(rb_eRuntimeError, "Unknown symbol \"%s\".", name);
196 #endif
197 };
198 val = rb_dlsym_new(func, name, stype);
199
200 return val;
201 }
202
203 void
204 Init_dlhandle()
205 {
206 rb_cDLHandle = rb_define_class_under(rb_mDL, "Handle", rb_cObject);
207 rb_define_singleton_method(rb_cDLHandle, "allocate", rb_dlhandle_s_allocate, 0);
208 rb_define_method(rb_cDLHandle, "initialize", rb_dlhandle_initialize, -1);
209 rb_define_method(rb_cDLHandle, "to_i", rb_dlhandle_to_i, 0);
210 rb_define_method(rb_cDLHandle, "to_ptr", rb_dlhandle_to_ptr, 0);
211 rb_define_method(rb_cDLHandle, "close", rb_dlhandle_close, 0);
212 rb_define_method(rb_cDLHandle, "sym", rb_dlhandle_sym, -1);
213 rb_define_method(rb_cDLHandle, "[]", rb_dlhandle_sym, -1);
214 rb_define_method(rb_cDLHandle, "disable_close", rb_dlhandle_disable_close, 0);
215 rb_define_method(rb_cDLHandle, "enable_close", rb_dlhandle_enable_close, 0);
216 }