DEFINITIONS
This source file includes following functions.
- rb_dl_scan_callback_args
- init_dl_func_table
- dlmalloc
- dlrealloc
- dlfree
- dlstrdup
- dlsizeof
- c_farray
- c_darray
- c_larray
- c_iarray
- c_harray
- c_carray
- c_parray
- rb_ary2cary
- rb_str_to_ptr
- rb_ary_to_ptr
- rb_io_to_ptr
- rb_dl_dlopen
- rb_dl_malloc
- rb_dl_strdup
- rb_dl_sizeof
- rb_dl_callback
- rb_dl_remove_callback
- Init_dl
1
2
3
4
5 #include <ruby.h>
6 #include <rubyio.h>
7 #include <ctype.h>
8 #include "dl.h"
9
10 VALUE rb_mDL;
11 VALUE rb_eDLError;
12 VALUE rb_eDLTypeError;
13
14 static VALUE DLFuncTable;
15 static void *rb_dl_callback_table[CALLBACK_TYPES][MAX_CALLBACK];
16 static ID id_call;
17
18 static int
19 rb_dl_scan_callback_args(long stack[], const char *proto,
20 int *argc, VALUE argv[])
21 {
22 int i;
23 long *sp;
24 VALUE val;
25
26 sp = stack;
27 for( i=1; proto[i]; i++ ){
28 switch( proto[i] ){
29 case 'C':
30 {
31 char v;
32 v = (char)(*sp);
33 sp++;
34 val = INT2NUM(v);
35 }
36 break;
37 case 'H':
38 {
39 short v;
40 v = (short)(*sp);
41 sp++;
42 val = INT2NUM(v);
43 }
44 break;
45 case 'I':
46 {
47 int v;
48 v = (int)(*sp);
49 sp++;
50 val = INT2NUM(v);
51 }
52 break;
53 case 'L':
54 {
55 long v;
56 v = (long)(*sp);
57 sp++;
58 val = INT2NUM(v);
59 }
60 break;
61 case 'F':
62 {
63 float v;
64 memcpy(&v, sp, sizeof(float));
65 sp += sizeof(float)/sizeof(long);
66 val = rb_float_new(v);
67 }
68 break;
69 case 'D':
70 {
71 double v;
72 memcpy(&v, sp, sizeof(double));
73 sp += sizeof(double)/sizeof(long);
74 val = rb_float_new(v);
75 }
76 break;
77 case 'P':
78 {
79 void *v;
80 memcpy(&v, sp, sizeof(void*));
81 sp++;
82 val = rb_dlptr_new(v, 0, 0);
83 }
84 break;
85 case 'S':
86 {
87 char *v;
88 memcpy(&v, sp, sizeof(void*));
89 sp++;
90 val = rb_tainted_str_new2(v);
91 }
92 break;
93 default:
94 rb_raise(rb_eDLTypeError, "unsupported type `%c'", proto[i]);
95 break;
96 }
97 argv[i-1] = val;
98 }
99 *argc = (i - 1);
100
101 return (*argc);
102 }
103
104 #include "callback.func"
105
106 static void
107 init_dl_func_table(){
108 #include "cbtable.func"
109 }
110
111 void *
112 dlmalloc(size_t size)
113 {
114 DEBUG_CODE2({
115 void *ptr;
116
117 printf("dlmalloc(%d)",size);
118 ptr = xmalloc(size);
119 printf(":0x%x\n",ptr);
120 return ptr;
121 },
122 {
123 return xmalloc(size);
124 });
125 }
126
127 void *
128 dlrealloc(void *ptr, size_t size)
129 {
130 DEBUG_CODE({
131 printf("dlrealloc(0x%x,%d)\n",ptr,size);
132 });
133 return xrealloc(ptr, size);
134 }
135
136 void
137 dlfree(void *ptr)
138 {
139 DEBUG_CODE({
140 printf("dlfree(0x%x)\n",ptr);
141 });
142 xfree(ptr);
143 }
144
145 char*
146 dlstrdup(const char *str)
147 {
148 char *newstr;
149
150 newstr = (char*)dlmalloc(strlen(str));
151 strcpy(newstr,str);
152
153 return newstr;
154 }
155
156 size_t
157 dlsizeof(const char *cstr)
158 {
159 size_t size;
160 int i, len, n, dlen;
161 char *d;
162
163 len = strlen(cstr);
164 size = 0;
165 for( i=0; i<len; i++ ){
166 n = 1;
167 if( isdigit(cstr[i+1]) ){
168 dlen = 1;
169 while( isdigit(cstr[i+dlen]) ){ dlen ++; };
170 dlen --;
171 d = ALLOCA_N(char, dlen + 1);
172 strncpy(d, cstr + i + 1, dlen);
173 d[dlen] = '\0';
174 n = atoi(d);
175 }
176 else{
177 dlen = 0;
178 };
179
180 switch( cstr[i] ){
181 case 'I':
182 DLALIGN(0,size,INT_ALIGN);
183 case 'i':
184 size += sizeof(int) * n;
185 break;
186 case 'L':
187 DLALIGN(0,size,LONG_ALIGN);
188 case 'l':
189 size += sizeof(long) * n;
190 break;
191 case 'F':
192 DLALIGN(0,size,FLOAT_ALIGN);
193 case 'f':
194 size += sizeof(float) * n;
195 break;
196 case 'D':
197 DLALIGN(0,size,DOUBLE_ALIGN);
198 case 'd':
199 size += sizeof(double) * n;
200 break;
201 case 'C':
202 case 'c':
203 size += sizeof(char) * n;
204 break;
205 case 'H':
206 DLALIGN(0,size,SHORT_ALIGN);
207 case 'h':
208 size += sizeof(short) * n;
209 break;
210 case 'P':
211 DLALIGN(0,size,VOIDP_ALIGN);
212 case 'p':
213 size += sizeof(void*) * n;
214 break;
215 default:
216 rb_raise(rb_eDLTypeError, "unexpected type '%c'", cstr[i]);
217 break;
218 };
219 i += dlen;
220 };
221
222 return size;
223 }
224
225 static float *
226 c_farray(VALUE v, long *size)
227 {
228 int i, len;
229 float *ary;
230 VALUE e;
231
232 len = RARRAY(v)->len;
233 *size = sizeof(float) * len;
234 ary = dlmalloc(*size);
235 for( i=0; i < len; i++ ){
236 e = rb_ary_entry(v, i);
237 switch( TYPE(e) ){
238 case T_FLOAT:
239 ary[i] = (float)(RFLOAT(e)->value);
240 break;
241 case T_NIL:
242 ary[i] = 0.0;
243 break;
244 default:
245 rb_raise(rb_eDLTypeError, "unexpected type of the element #%d", i);
246 break;
247 };
248 };
249
250 return ary;
251 }
252
253 static double *
254 c_darray(VALUE v, long *size)
255 {
256 int i, len;
257 double *ary;
258 VALUE e;
259
260 len = RARRAY(v)->len;
261 *size = sizeof(double) * len;
262 ary = dlmalloc(*size);
263 for( i=0; i < len; i++ ){
264 e = rb_ary_entry(v, i);
265 switch( TYPE(e) ){
266 case T_FLOAT:
267 ary[i] = (double)(RFLOAT(e)->value);
268 break;
269 case T_NIL:
270 ary[i] = 0.0;
271 break;
272 default:
273 rb_raise(rb_eDLTypeError, "unexpected type of the element #%d", i);
274 break;
275 };
276 };
277
278 return ary;
279 }
280
281 static long *
282 c_larray(VALUE v, long *size)
283 {
284 int i, len;
285 long *ary;
286 VALUE e;
287
288 len = RARRAY(v)->len;
289 *size = sizeof(long) * len;
290 ary = dlmalloc(*size);
291 for( i=0; i < len; i++ ){
292 e = rb_ary_entry(v, i);
293 switch( TYPE(e) ){
294 case T_FIXNUM:
295 case T_BIGNUM:
296 ary[i] = (long)(NUM2INT(e));
297 break;
298 case T_NIL:
299 ary[i] = 0;
300 break;
301 default:
302 rb_raise(rb_eDLTypeError, "unexpected type of the element #%d", i);
303 break;
304 };
305 };
306
307 return ary;
308 }
309
310 static int *
311 c_iarray(VALUE v, long *size)
312 {
313 int i, len;
314 int *ary;
315 VALUE e;
316
317 len = RARRAY(v)->len;
318 *size = sizeof(int) * len;
319 ary = dlmalloc(*size);
320 for( i=0; i < len; i++ ){
321 e = rb_ary_entry(v, i);
322 switch( TYPE(e) ){
323 case T_FIXNUM:
324 case T_BIGNUM:
325 ary[i] = (int)(NUM2INT(e));
326 break;
327 case T_NIL:
328 ary[i] = 0;
329 break;
330 default:
331 rb_raise(rb_eDLTypeError, "unexpected type of the element #%d", i);
332 break;
333 };
334 };
335
336 return ary;
337 }
338
339 static short *
340 c_harray(VALUE v, long *size)
341 {
342 int i, len;
343 short *ary;
344 VALUE e;
345
346 len = RARRAY(v)->len;
347 *size = sizeof(short) * len;
348 ary = dlmalloc(*size);
349 for( i=0; i < len; i++ ){
350 e = rb_ary_entry(v, i);
351 switch( TYPE(e) ){
352 case T_FIXNUM:
353 case T_BIGNUM:
354 ary[i] = (short)(NUM2INT(e));
355 break;
356 case T_NIL:
357 ary[i] = 0;
358 break;
359 default:
360 rb_raise(rb_eDLTypeError, "unexpected type of the element #%d", i);
361 break;
362 };
363 };
364
365 return ary;
366 }
367
368 static char *
369 c_carray(VALUE v, long *size)
370 {
371 int i, len;
372 char *ary;
373 VALUE e;
374
375 len = RARRAY(v)->len;
376 *size = sizeof(char) * len;
377 ary = dlmalloc(*size);
378 for( i=0; i < len; i++ ){
379 e = rb_ary_entry(v, i);
380 switch( TYPE(e) ){
381 case T_FIXNUM:
382 case T_BIGNUM:
383 ary[i] = (char)(NUM2INT(e));
384 break;
385 case T_NIL:
386 ary[i] = 0;
387 break;
388 default:
389 rb_raise(rb_eDLTypeError, "unexpected type of the element #%d", i);
390 break;
391 };
392 };
393
394 return ary;
395 }
396
397 static void *
398 c_parray(VALUE v, long *size)
399 {
400 int i, len;
401 void **ary;
402 VALUE e;
403
404 len = RARRAY(v)->len;
405 *size = sizeof(void*) * len;
406 ary = dlmalloc(*size);
407 for( i=0; i < len; i++ ){
408 e = rb_ary_entry(v, i);
409 switch( TYPE(e) ){
410 case T_STRING:
411 {
412 char *str, *src;
413 src = RSTRING(e)->ptr;
414 str = dlstrdup(src);
415 ary[i] = (void*)str;
416 };
417 break;
418 case T_NIL:
419 ary[i] = NULL;
420 break;
421 case T_DATA:
422 if( rb_obj_is_kind_of(e, rb_cDLPtrData) ){
423 struct ptr_data *pdata;
424 Data_Get_Struct(e, struct ptr_data, pdata);
425 ary[i] = (void*)(pdata->ptr);
426 }
427 else{
428 rb_raise(rb_eDLTypeError, "unexpected type of the element #%d", i);
429 };
430 break;
431 default:
432 rb_raise(rb_eDLTypeError, "unexpected type of the element #%d", i);
433 break;
434 };
435 };
436
437 return ary;
438 }
439
440 void *
441 rb_ary2cary(char t, VALUE v, long *size)
442 {
443 int len;
444 VALUE val0;
445
446 if( TYPE(v) != T_ARRAY ){
447 rb_raise(rb_eDLTypeError, "an array is expected.");
448 };
449
450 len = RARRAY(v)->len;
451 if( len == 0 ){
452 return NULL;
453 };
454
455 if( !size ){
456 size = ALLOCA_N(long,1);
457 };
458
459 val0 = rb_ary_entry(v,0);
460 switch( TYPE(val0) ){
461 case T_FIXNUM:
462 case T_BIGNUM:
463 switch( t ){
464 case 'C': case 'c':
465 return (void*)c_carray(v,size);
466 case 'H': case 'h':
467 return (void*)c_harray(v,size);
468 case 'I': case 'i':
469 return (void*)c_iarray(v,size);
470 case 'L': case 'l': case 0:
471 return (void*)c_larray(v,size);
472 default:
473 rb_raise(rb_eDLTypeError, "type mismatch");
474 };
475 case T_STRING:
476 return (void*)c_parray(v,size);
477 case T_FLOAT:
478 switch( t ){
479 case 'F': case 'f':
480 return (void*)c_farray(v,size);
481 case 'D': case 'd': case 0:
482 return (void*)c_darray(v,size);
483 };
484 rb_raise(rb_eDLTypeError, "type mismatch");
485 case T_DATA:
486 if( rb_obj_is_kind_of(val0, rb_cDLPtrData) ){
487 return (void*)c_parray(v,size);
488 };
489 rb_raise(rb_eDLTypeError, "type mismatch");
490 default:
491 rb_raise(rb_eDLTypeError, "unsupported type");
492 };
493 }
494
495 VALUE
496 rb_str_to_ptr(VALUE self)
497 {
498 char *ptr;
499 int len;
500
501 len = RSTRING(self)->len;
502 ptr = (char*)dlmalloc(len + 1);
503 memcpy(ptr, RSTRING(self)->ptr, len);
504 ptr[len] = '\0';
505 return rb_dlptr_new((void*)ptr,len,dlfree);
506 }
507
508 VALUE
509 rb_ary_to_ptr(int argc, VALUE argv[], VALUE self)
510 {
511 void *ptr;
512 VALUE t;
513 long size;
514
515 switch( rb_scan_args(argc, argv, "01", &t) ){
516 case 1:
517 ptr = rb_ary2cary(StringValuePtr(t)[0], self, &size);
518 break;
519 case 0:
520 ptr = rb_ary2cary(0, self, &size);
521 break;
522 };
523 return ptr ? rb_dlptr_new(ptr, size, dlfree) : Qnil;
524 }
525
526 VALUE
527 rb_io_to_ptr(VALUE self)
528 {
529 OpenFile *fptr;
530 FILE *fp;
531
532 GetOpenFile(self, fptr);
533 fp = fptr->f;
534
535 return fp ? rb_dlptr_new(fp, sizeof(FILE), 0) : Qnil;
536 };
537
538 VALUE
539 rb_dl_dlopen(int argc, VALUE argv[], VALUE self)
540 {
541 return rb_class_new_instance(argc, argv, rb_cDLHandle);
542 }
543
544 VALUE
545 rb_dl_malloc(VALUE self, VALUE size)
546 {
547 return rb_dlptr_malloc(DLNUM2LONG(size), dlfree);
548 }
549
550 VALUE
551 rb_dl_strdup(VALUE self, VALUE str)
552 {
553 void *p;
554
555 str = rb_String(str);
556 return rb_dlptr_new(strdup(RSTRING(str)->ptr), RSTRING(str)->len, dlfree);
557 }
558
559 static VALUE
560 rb_dl_sizeof(VALUE self, VALUE str)
561 {
562 return INT2NUM(dlsizeof(StringValuePtr(str)));
563 }
564
565 static VALUE
566 rb_dl_callback(int argc, VALUE argv[], VALUE self)
567 {
568 VALUE type, proc;
569 int rettype, entry, i;
570 char fname[127];
571
572 proc = Qnil;
573 switch( rb_scan_args(argc, argv, "11", &type, &proc) ){
574 case 1:
575 if( rb_block_given_p() ){
576 proc = rb_f_lambda();
577 }
578 else{
579 proc = Qnil;
580 }
581 default:
582 break;
583 }
584
585 Check_Type(type, T_STRING);
586 switch( RSTRING(type)->ptr[0] ){
587 case '0':
588 rettype = 0x00;
589 break;
590 case 'C':
591 rettype = 0x01;
592 break;
593 case 'H':
594 rettype = 0x02;
595 break;
596 case 'I':
597 rettype = 0x03;
598 break;
599 case 'L':
600 rettype = 0x04;
601 break;
602 case 'F':
603 rettype = 0x05;
604 break;
605 case 'D':
606 rettype = 0x06;
607 break;
608 case 'P':
609 rettype = 0x07;
610 break;
611 default:
612 rb_raise(rb_eDLTypeError, "unsupported type `%c'", RSTRING(type)->ptr[0]);
613 }
614
615 entry = -1;
616 for( i=0; i < MAX_CALLBACK; i++ ){
617 if( rb_hash_aref(DLFuncTable, rb_assoc_new(INT2NUM(rettype), INT2NUM(i))) == Qnil ){
618 entry = i;
619 break;
620 }
621 }
622 if( entry < 0 ){
623 rb_raise(rb_eDLError, "too many callbacks are defined.");
624 }
625
626 rb_hash_aset(DLFuncTable,
627 rb_assoc_new(INT2NUM(rettype),INT2NUM(entry)),
628 rb_assoc_new(type,proc));
629 sprintf(fname, "rb_dl_callback_func_%d_%d", rettype, entry);
630 return rb_dlsym_new((void (*)())rb_dl_callback_table[rettype][entry],
631 fname, RSTRING(type)->ptr);
632 }
633
634 static VALUE
635 rb_dl_remove_callback(VALUE mod, VALUE sym)
636 {
637 freefunc_t f = rb_dlsym2csym(sym);
638 int i, j;
639
640 for( i=0; i < CALLBACK_TYPES; i++ ){
641 for( j=0; j < MAX_CALLBACK; j++ ){
642 if( rb_dl_callback_table[i][j] == f ){
643 rb_hash_aset(DLFuncTable, rb_assoc_new(INT2NUM(i),INT2NUM(j)),Qnil);
644 break;
645 }
646 }
647 }
648 return Qnil;
649 }
650
651 void
652 Init_dl()
653 {
654 void Init_dlptr();
655 void Init_dlsym();
656 void Init_dlhandle();
657
658 id_call = rb_intern("call");
659
660 rb_mDL = rb_define_module("DL");
661
662 rb_eDLError = rb_define_class_under(rb_mDL, "DLError", rb_eStandardError);
663 rb_eDLTypeError = rb_define_class_under(rb_mDL, "DLTypeError", rb_eDLError);
664
665 DLFuncTable = rb_hash_new();
666 init_dl_func_table();
667 rb_define_const(rb_mDL, "FuncTable", DLFuncTable);
668
669 rb_define_const(rb_mDL, "RTLD_GLOBAL", INT2NUM(RTLD_GLOBAL));
670 rb_define_const(rb_mDL, "RTLD_LAZY", INT2NUM(RTLD_LAZY));
671 rb_define_const(rb_mDL, "RTLD_NOW", INT2NUM(RTLD_NOW));
672
673 rb_define_const(rb_mDL, "ALIGN_INT", INT2NUM(ALIGN_INT));
674 rb_define_const(rb_mDL, "ALIGN_LONG", INT2NUM(ALIGN_LONG));
675 rb_define_const(rb_mDL, "ALIGN_FLOAT", INT2NUM(ALIGN_FLOAT));
676 rb_define_const(rb_mDL, "ALIGN_SHORT", INT2NUM(ALIGN_SHORT));
677 rb_define_const(rb_mDL, "ALIGN_DOUBLE",INT2NUM(ALIGN_DOUBLE));
678 rb_define_const(rb_mDL, "ALIGN_VOIDP", INT2NUM(ALIGN_VOIDP));
679
680 rb_define_const(rb_mDL, "VERSION", rb_tainted_str_new2(DL_VERSION));
681 rb_define_const(rb_mDL, "MAJOR_VERSION", INT2NUM(DL_MAJOR_VERSION));
682 rb_define_const(rb_mDL, "MINOR_VERSION", INT2NUM(DL_MINOR_VERSION));
683 rb_define_const(rb_mDL, "PATCH_VERSION", INT2NUM(DL_PATCH_VERSION));
684 rb_define_const(rb_mDL, "MAX_ARG", INT2NUM(MAX_ARG));
685 rb_define_const(rb_mDL, "DLSTACK", rb_tainted_str_new2(DLSTACK_METHOD));
686
687 rb_define_module_function(rb_mDL, "dlopen", rb_dl_dlopen, -1);
688 rb_define_module_function(rb_mDL, "callback", rb_dl_callback, -1);
689 rb_define_module_function(rb_mDL, "define_callback", rb_dl_callback, -1);
690 rb_define_module_function(rb_mDL, "remove_callback", rb_dl_remove_callback, 1);
691 rb_define_module_function(rb_mDL, "malloc", rb_dl_malloc, 1);
692 rb_define_module_function(rb_mDL, "strdup", rb_dl_strdup, 1);
693 rb_define_module_function(rb_mDL, "sizeof", rb_dl_sizeof, 1);
694
695 Init_dlptr();
696 Init_dlsym();
697 Init_dlhandle();
698
699 rb_define_const(rb_mDL, "FREE", rb_dlsym_new(dlfree, "free", "0P"));
700
701 rb_define_method(rb_cString, "to_ptr", rb_str_to_ptr, 0);
702 rb_define_method(rb_cArray, "to_ptr", rb_ary_to_ptr, -1);
703 rb_define_method(rb_cIO, "to_ptr", rb_io_to_ptr, 0);
704 }