rubysl-dl 0.0.1 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,63 @@
1
+ # -*- ruby -*-
2
+
3
+ require 'mkmf'
4
+ $:.unshift File.dirname(__FILE__)
5
+ require 'type'
6
+ require 'dlconfig'
7
+
8
+ if name = ARGV.shift
9
+ OUTPUT = File.open name, "wb"
10
+ at_exit { OUTPUT.close }
11
+ else
12
+ OUTPUT = STDOUT
13
+ end
14
+
15
+ def mkfunc(rettype, fnum, argc)
16
+ args = (0..(argc-1)).collect{|i| "long arg#{i}"}.join(", ")
17
+
18
+ subst_code = (0..(argc-1)).collect{|i|
19
+ " buff[#{i.to_s}] = arg#{i.to_s};"
20
+ }.join("\n")
21
+
22
+ ret_code =
23
+ if( DLTYPE[rettype][:c2rb] )
24
+ " return #{DLTYPE[rettype][:rb2c]['retval']};"
25
+ else
26
+ " /* no return value */"
27
+ end
28
+
29
+ code = [
30
+ "static #{DLTYPE[rettype][:ctype]}",
31
+ "rb_dl_callback_func_#{rettype.to_s}_#{fnum.to_s}(#{args})",
32
+ "{",
33
+ " VALUE retval, proto, proc, obj;",
34
+ " VALUE argv[#{argc.to_s}];",
35
+ " int argc;",
36
+ " long buff[#{argc.to_s}];",
37
+ "",
38
+ subst_code,
39
+ "",
40
+ " obj = rb_hash_aref(DLFuncTable, rb_assoc_new(INT2NUM(#{rettype.to_s}),INT2NUM(#{fnum.to_s})));",
41
+ " if(NIL_P(obj))",
42
+ " rb_raise(rb_eDLError, \"callback function does not exist in DL::FuncTable\");",
43
+ " Check_Type(obj, T_ARRAY);",
44
+ " proto = rb_ary_entry(obj, 0);",
45
+ " proc = rb_ary_entry(obj, 1);",
46
+ " Check_Type(proto, T_STRING);",
47
+ " if( RSTRING(proto)->len >= #{argc.to_s} )",
48
+ " rb_raise(rb_eArgError, \"too many arguments\");",
49
+ " rb_dl_scan_callback_args(buff, RSTRING(proto)->ptr, &argc, argv);",
50
+ " retval = rb_funcall2(proc, id_call, argc, argv);",
51
+ "",
52
+ ret_code,
53
+ "}",
54
+ ].join("\n")
55
+
56
+ return code
57
+ end
58
+
59
+ DLTYPE.keys.sort.each{|t|
60
+ for n in 0..(MAX_CALLBACK - 1)
61
+ OUTPUT.print(mkfunc(t, n, 15), "\n\n")
62
+ end
63
+ }
@@ -0,0 +1,25 @@
1
+ # -*- ruby -*-
2
+
3
+ require 'mkmf'
4
+ $:.unshift File.dirname(__FILE__)
5
+ require 'type'
6
+ require 'dlconfig'
7
+
8
+ if name = ARGV.shift
9
+ OUTPUT = File.open name, "wb"
10
+ at_exit { OUTPUT.close }
11
+ else
12
+ OUTPUT = STDOUT
13
+ end
14
+
15
+ def mktable(rettype, fnum, argc)
16
+ code =
17
+ "rb_dl_callback_table[#{rettype}][#{fnum}] = &rb_dl_callback_func_#{rettype.to_s}_#{fnum};"
18
+ return code
19
+ end
20
+
21
+ DLTYPE.keys.sort.each{|t|
22
+ for n in 0..(MAX_CALLBACK - 1)
23
+ OUTPUT.print(mktable(t, n, 15), "\n")
24
+ end
25
+ }
@@ -0,0 +1,1062 @@
1
+ /* -*- C -*-
2
+ * $Id: ptr.c 15471 2008-02-14 08:46:06Z matz $
3
+ */
4
+
5
+ #include "ruby.h"
6
+ #include <ctype.h>
7
+ #ifdef HAVE_RUBY_ST_H
8
+ #include "ruby/st.h"
9
+ #else
10
+ #include "st.h"
11
+ #endif
12
+ #include "dl.h"
13
+
14
+ VALUE rb_cDLPtrData;
15
+ VALUE rb_mDLMemorySpace;
16
+ static st_table* st_memory_table;
17
+
18
+ #ifndef T_SYMBOL
19
+ # define T_SYMBOL T_FIXNUM
20
+ #endif
21
+
22
+ static void
23
+ rb_dlmem_delete(void *ptr)
24
+ {
25
+ st_delete(st_memory_table, (st_data_t*)&ptr, NULL);
26
+ }
27
+
28
+ static void
29
+ rb_dlmem_aset(void *ptr, VALUE obj)
30
+ {
31
+ if (obj == Qnil) {
32
+ rb_dlmem_delete(ptr);
33
+ }
34
+ else{
35
+ st_insert(st_memory_table, (st_data_t)ptr, (st_data_t)obj);
36
+ }
37
+ }
38
+
39
+ static VALUE
40
+ rb_dlmem_aref(void *ptr)
41
+ {
42
+ VALUE val;
43
+
44
+ if(!st_lookup(st_memory_table, (st_data_t)ptr, (st_data_t*)(&val))) return Qnil;
45
+ return val == Qundef ? Qnil : val;
46
+ }
47
+
48
+ void
49
+ dlptr_free(struct ptr_data *data)
50
+ {
51
+ if (data->ptr) {
52
+ DEBUG_CODE({
53
+ printf("dlptr_free(): removing the pointer `0x%x' from the MemorySpace\n",
54
+ data->ptr);
55
+ });
56
+ rb_dlmem_delete(data->ptr);
57
+ if (data->free) {
58
+ DEBUG_CODE({
59
+ printf("dlptr_free(): 0x%x(data->ptr:0x%x)\n",data->free,data->ptr);
60
+ });
61
+ (*(data->free))(data->ptr);
62
+ }
63
+ }
64
+ if (data->stype) dlfree(data->stype);
65
+ if (data->ssize) dlfree(data->ssize);
66
+ if (data->ids) dlfree(data->ids);
67
+ }
68
+
69
+ void
70
+ dlptr_init(VALUE val)
71
+ {
72
+ struct ptr_data *data;
73
+
74
+ Data_Get_Struct(val, struct ptr_data, data);
75
+ DEBUG_CODE({
76
+ printf("dlptr_init(): add the pointer `0x%x' to the MemorySpace\n",
77
+ data->ptr);
78
+ });
79
+ rb_dlmem_aset(data->ptr, val);
80
+ OBJ_TAINT(val);
81
+ }
82
+
83
+ VALUE
84
+ rb_dlptr_new2(VALUE klass, void *ptr, long size, freefunc_t func)
85
+ {
86
+ struct ptr_data *data;
87
+ VALUE val;
88
+
89
+ rb_secure(4);
90
+ if (ptr) {
91
+ val = rb_dlmem_aref(ptr);
92
+ if (val == Qnil) {
93
+ val = Data_Make_Struct(klass, struct ptr_data,
94
+ 0, dlptr_free, data);
95
+ data->ptr = ptr;
96
+ data->free = func;
97
+ data->ctype = DLPTR_CTYPE_UNKNOWN;
98
+ data->stype = NULL;
99
+ data->ssize = NULL;
100
+ data->slen = 0;
101
+ data->size = size;
102
+ data->ids = NULL;
103
+ data->ids_num = 0;
104
+ dlptr_init(val);
105
+ }
106
+ else{
107
+ if (func) {
108
+ Data_Get_Struct(val, struct ptr_data, data);
109
+ data->free = func;
110
+ }
111
+ }
112
+ }
113
+ else{
114
+ val = Qnil;
115
+ }
116
+
117
+ return val;
118
+ }
119
+
120
+ VALUE
121
+ rb_dlptr_new(void *ptr, long size, freefunc_t func)
122
+ {
123
+ return rb_dlptr_new2(rb_cDLPtrData, ptr, size, func);
124
+ }
125
+
126
+ VALUE
127
+ rb_dlptr_malloc(long size, freefunc_t func)
128
+ {
129
+ void *ptr;
130
+
131
+ rb_secure(4);
132
+ ptr = dlmalloc((size_t)size);
133
+ memset(ptr,0,(size_t)size);
134
+ return rb_dlptr_new(ptr, size, func);
135
+ }
136
+
137
+ void *
138
+ rb_dlptr2cptr(VALUE val)
139
+ {
140
+ struct ptr_data *data;
141
+ void *ptr;
142
+
143
+ if (rb_obj_is_kind_of(val, rb_cDLPtrData)) {
144
+ Data_Get_Struct(val, struct ptr_data, data);
145
+ ptr = data->ptr;
146
+ }
147
+ else if (val == Qnil) {
148
+ ptr = NULL;
149
+ }
150
+ else{
151
+ rb_raise(rb_eTypeError, "DL::PtrData was expected");
152
+ }
153
+
154
+ return ptr;
155
+ }
156
+
157
+ static VALUE
158
+ rb_dlptr_s_allocate(VALUE klass)
159
+ {
160
+ VALUE obj;
161
+ struct ptr_data *data;
162
+
163
+ rb_secure(4);
164
+ obj = Data_Make_Struct(klass, struct ptr_data, 0, dlptr_free, data);
165
+ data->ptr = 0;
166
+ data->free = 0;
167
+ data->ctype = DLPTR_CTYPE_UNKNOWN;
168
+ data->stype = NULL;
169
+ data->ssize = NULL;
170
+ data->slen = 0;
171
+ data->size = 0;
172
+ data->ids = NULL;
173
+ data->ids_num = 0;
174
+
175
+ return obj;
176
+ }
177
+
178
+ static VALUE
179
+ rb_dlptr_initialize(int argc, VALUE argv[], VALUE self)
180
+ {
181
+ VALUE ptr, sym, size;
182
+ struct ptr_data *data;
183
+ void *p = NULL;
184
+ freefunc_t f = NULL;
185
+ long s = 0;
186
+
187
+ switch (rb_scan_args(argc, argv, "12", &ptr, &size, &sym)) {
188
+ case 1:
189
+ p = (void*)(DLNUM2LONG(rb_Integer(ptr)));
190
+ break;
191
+ case 2:
192
+ p = (void*)(DLNUM2LONG(rb_Integer(ptr)));
193
+ s = DLNUM2LONG(size);
194
+ break;
195
+ case 3:
196
+ p = (void*)(DLNUM2LONG(rb_Integer(ptr)));
197
+ s = DLNUM2LONG(size);
198
+ f = rb_dlsym2csym(sym);
199
+ break;
200
+ default:
201
+ rb_bug("rb_dlptr_initialize");
202
+ }
203
+
204
+ if (p) {
205
+ Data_Get_Struct(self, struct ptr_data, data);
206
+ if (data->ptr && data->free) {
207
+ /* Free previous memory. Use of inappropriate initialize may cause SEGV. */
208
+ (*(data->free))(data->ptr);
209
+ }
210
+ data->ptr = p;
211
+ data->size = s;
212
+ data->free = f;
213
+ }
214
+
215
+ return Qnil;
216
+ }
217
+
218
+ static VALUE
219
+ rb_dlptr_s_malloc(int argc, VALUE argv[], VALUE klass)
220
+ {
221
+ VALUE size, sym, obj;
222
+ int s = 0;
223
+ freefunc_t f = NULL;
224
+
225
+ switch (rb_scan_args(argc, argv, "11", &size, &sym)) {
226
+ case 1:
227
+ s = NUM2INT(size);
228
+ break;
229
+ case 2:
230
+ s = NUM2INT(size);
231
+ f = rb_dlsym2csym(sym);
232
+ break;
233
+ default:
234
+ rb_bug("rb_dlptr_s_malloc");
235
+ }
236
+
237
+ obj = rb_dlptr_malloc(s,f);
238
+
239
+ return obj;
240
+ }
241
+
242
+ VALUE
243
+ rb_dlptr_to_i(VALUE self)
244
+ {
245
+ struct ptr_data *data;
246
+
247
+ Data_Get_Struct(self, struct ptr_data, data);
248
+ return DLLONG2NUM(data->ptr);
249
+ }
250
+
251
+ VALUE
252
+ rb_dlptr_ptr(VALUE self)
253
+ {
254
+ struct ptr_data *data;
255
+
256
+ Data_Get_Struct(self, struct ptr_data, data);
257
+ return rb_dlptr_new(*((void**)(data->ptr)),0,0);
258
+ }
259
+
260
+ VALUE
261
+ rb_dlptr_ref(VALUE self)
262
+ {
263
+ struct ptr_data *data;
264
+
265
+ Data_Get_Struct(self, struct ptr_data, data);
266
+ return rb_dlptr_new(&(data->ptr),0,0);
267
+ }
268
+
269
+ VALUE
270
+ rb_dlptr_null_p(VALUE self)
271
+ {
272
+ struct ptr_data *data;
273
+
274
+ Data_Get_Struct(self, struct ptr_data, data);
275
+ return data->ptr ? Qfalse : Qtrue;
276
+ }
277
+
278
+ VALUE
279
+ rb_dlptr_free_set(VALUE self, VALUE val)
280
+ {
281
+ struct ptr_data *data;
282
+
283
+ Data_Get_Struct(self, struct ptr_data, data);
284
+
285
+ data->free = DLFREEFUNC(rb_dlsym2csym(val));
286
+
287
+ return Qnil;
288
+ }
289
+
290
+ VALUE
291
+ rb_dlptr_free_get(VALUE self)
292
+ {
293
+ struct ptr_data *pdata;
294
+
295
+ Data_Get_Struct(self, struct ptr_data, pdata);
296
+
297
+ return rb_dlsym_new(pdata->free,"(free)","0P");
298
+ }
299
+
300
+ VALUE
301
+ rb_dlptr_to_array(int argc, VALUE argv[], VALUE self)
302
+ {
303
+ struct ptr_data *data;
304
+ int n = 0;
305
+ int i;
306
+ int t = 0;
307
+ VALUE ary;
308
+ VALUE type, size;
309
+
310
+ Data_Get_Struct(self, struct ptr_data, data);
311
+
312
+ switch (rb_scan_args(argc, argv, "11", &type, &size)) {
313
+ case 2:
314
+ t = StringValuePtr(type)[0];
315
+ n = NUM2INT(size);
316
+ break;
317
+ case 1:
318
+ t = StringValuePtr(type)[0];
319
+ switch (t) {
320
+ case 'C':
321
+ n = data->size;
322
+ break;
323
+ case 'H':
324
+ n = data->size / sizeof(short);
325
+ break;
326
+ case 'I':
327
+ n = data->size / sizeof(int);
328
+ break;
329
+ case 'L':
330
+ n = data->size / sizeof(long);
331
+ break;
332
+ case 'F':
333
+ n = data->size / sizeof(float);
334
+ break;
335
+ case 'D':
336
+ n = data->size / sizeof(double);
337
+ break;
338
+ case 'P': case 'p':
339
+ n = data->size / sizeof(void*);
340
+ break;
341
+ case 'S': case 's':
342
+ n = data->size / sizeof(char*);
343
+ break;
344
+ default:
345
+ n = 0;
346
+ }
347
+ break;
348
+ default:
349
+ rb_bug("rb_dlptr_to_array");
350
+ }
351
+
352
+ ary = rb_ary_new();
353
+
354
+ for (i=0; i < n; i++) {
355
+ switch (t) {
356
+ case 'C':
357
+ rb_ary_push(ary, INT2NUM(((char*)(data->ptr))[i]));
358
+ break;
359
+ case 'H':
360
+ rb_ary_push(ary, INT2NUM(((short*)(data->ptr))[i]));
361
+ break;
362
+ case 'I':
363
+ rb_ary_push(ary, INT2NUM(((int*)(data->ptr))[i]));
364
+ break;
365
+ case 'L':
366
+ rb_ary_push(ary, DLLONG2NUM(((long*)(data->ptr))[i]));
367
+ break;
368
+ case 'D':
369
+ rb_ary_push(ary, rb_float_new(((double*)(data->ptr))[i]));
370
+ break;
371
+ case 'F':
372
+ rb_ary_push(ary, rb_float_new(((float*)(data->ptr))[i]));
373
+ break;
374
+ case 'S':
375
+ {
376
+ char *str = ((char**)(data->ptr))[i];
377
+ if (str) {
378
+ rb_ary_push(ary, rb_tainted_str_new2(str));
379
+ }
380
+ else{
381
+ rb_ary_push(ary, Qnil);
382
+ }
383
+ }
384
+ break;
385
+ case 's':
386
+ {
387
+ char *str = ((char**)(data->ptr))[i];
388
+ if (str) {
389
+ rb_ary_push(ary, rb_tainted_str_new2(str));
390
+ xfree(str);
391
+ }
392
+ else{
393
+ rb_ary_push(ary, Qnil);
394
+ }
395
+ }
396
+ break;
397
+ case 'P':
398
+ rb_ary_push(ary, rb_dlptr_new(((void**)(data->ptr))[i],0,0));
399
+ break;
400
+ case 'p':
401
+ rb_ary_push(ary,
402
+ rb_dlptr_new(((void**)(data->ptr))[i],0,dlfree));
403
+ break;
404
+ }
405
+ }
406
+
407
+ return ary;
408
+ }
409
+
410
+
411
+ VALUE
412
+ rb_dlptr_to_s(int argc, VALUE argv[], VALUE self)
413
+ {
414
+ struct ptr_data *data;
415
+ VALUE arg1, val = Qnil;
416
+ int len;
417
+
418
+ Data_Get_Struct(self, struct ptr_data, data);
419
+ switch (rb_scan_args(argc, argv, "01", &arg1)) {
420
+ case 0:
421
+ val = rb_tainted_str_new2((char*)(data->ptr));
422
+ break;
423
+ case 1:
424
+ len = NUM2INT(arg1);
425
+ val = rb_tainted_str_new((char*)(data->ptr), len);
426
+ break;
427
+ default:
428
+ rb_bug("rb_dlptr_to_s");
429
+ }
430
+
431
+ return val;
432
+ }
433
+
434
+ VALUE
435
+ rb_dlptr_to_str(int argc, VALUE argv[], VALUE self)
436
+ {
437
+ struct ptr_data *data;
438
+ VALUE arg1, val = Qnil;
439
+ int len;
440
+
441
+ Data_Get_Struct(self, struct ptr_data, data);
442
+ switch (rb_scan_args(argc, argv, "01", &arg1)) {
443
+ case 0:
444
+ val = rb_tainted_str_new((char*)(data->ptr),data->size);
445
+ break;
446
+ case 1:
447
+ len = NUM2INT(arg1);
448
+ val = rb_tainted_str_new((char*)(data->ptr), len);
449
+ break;
450
+ default:
451
+ rb_bug("rb_dlptr_to_str");
452
+ }
453
+
454
+ return val;
455
+ }
456
+
457
+ VALUE
458
+ rb_dlptr_inspect(VALUE self)
459
+ {
460
+ struct ptr_data *data;
461
+ char str[1024];
462
+
463
+ Data_Get_Struct(self, struct ptr_data, data);
464
+ snprintf(str, 1023, "#<%s:0x%lx ptr=0x%lx size=%ld free=0x%lx>",
465
+ rb_class2name(CLASS_OF(self)), (long unsigned)data,
466
+ (long unsigned)data->ptr, data->size,
467
+ (long)data->free);
468
+ return rb_str_new2(str);
469
+ }
470
+
471
+ VALUE
472
+ rb_dlptr_eql(VALUE self, VALUE other)
473
+ {
474
+ void *ptr1, *ptr2;
475
+ ptr1 = rb_dlptr2cptr(self);
476
+ ptr2 = rb_dlptr2cptr(other);
477
+
478
+ return ptr1 == ptr2 ? Qtrue : Qfalse;
479
+ }
480
+
481
+ VALUE
482
+ rb_dlptr_cmp(VALUE self, VALUE other)
483
+ {
484
+ void *ptr1, *ptr2;
485
+ ptr1 = rb_dlptr2cptr(self);
486
+ ptr2 = rb_dlptr2cptr(other);
487
+ return DLLONG2NUM((long)ptr1 - (long)ptr2);
488
+ }
489
+
490
+ VALUE
491
+ rb_dlptr_plus(VALUE self, VALUE other)
492
+ {
493
+ void *ptr;
494
+ long num, size;
495
+
496
+ ptr = rb_dlptr2cptr(self);
497
+ size = RDLPTR(self)->size;
498
+ num = DLNUM2LONG(other);
499
+ return rb_dlptr_new((char *)ptr + num, size - num, 0);
500
+ }
501
+
502
+ VALUE
503
+ rb_dlptr_minus(VALUE self, VALUE other)
504
+ {
505
+ void *ptr;
506
+ long num, size;
507
+
508
+ ptr = rb_dlptr2cptr(self);
509
+ size = RDLPTR(self)->size;
510
+ num = DLNUM2LONG(other);
511
+ return rb_dlptr_new((char *)ptr - num, size + num, 0);
512
+ }
513
+
514
+ VALUE
515
+ rb_dlptr_define_data_type(int argc, VALUE argv[], VALUE self)
516
+ {
517
+ VALUE data_type, type, rest, vid;
518
+ struct ptr_data *data;
519
+ int i, t, num;
520
+ char *ctype;
521
+
522
+ rb_scan_args(argc, argv, "11*", &data_type, &type, &rest);
523
+ Data_Get_Struct(self, struct ptr_data, data);
524
+
525
+ if (argc == 1 || (argc == 2 && type == Qnil)) {
526
+ if (NUM2INT(data_type) == DLPTR_CTYPE_UNKNOWN) {
527
+ data->ctype = DLPTR_CTYPE_UNKNOWN;
528
+ data->slen = 0;
529
+ data->ids_num = 0;
530
+ if (data->stype) {
531
+ dlfree(data->stype);
532
+ data->stype = NULL;
533
+ }
534
+ if (data->ids) {
535
+ dlfree(data->ids);
536
+ data->ids = NULL;
537
+ }
538
+ return Qnil;
539
+ }
540
+ else{
541
+ rb_raise(rb_eArgError, "wrong arguments");
542
+ }
543
+ }
544
+
545
+ t = NUM2INT(data_type);
546
+ StringValue(type);
547
+ Check_Type(rest, T_ARRAY);
548
+ num = RARRAY_LEN(rest);
549
+ for (i=0; i<num; i++) {
550
+ rb_to_id(rb_ary_entry(rest,i));
551
+ }
552
+
553
+ data->ctype = t;
554
+ data->slen = num;
555
+ data->ids_num = num;
556
+ if (data->stype) dlfree(data->stype);
557
+ data->stype = (char*)dlmalloc(sizeof(char) * num);
558
+ if (data->ssize) dlfree(data->ssize);
559
+ data->ssize = (int*)dlmalloc(sizeof(int) * num);
560
+ if (data->ids) dlfree(data->ids);
561
+ data->ids = (ID*)dlmalloc(sizeof(ID) * data->ids_num);
562
+
563
+ ctype = StringValuePtr(type);
564
+ for (i=0; i<num; i++) {
565
+ vid = rb_ary_entry(rest,i);
566
+ data->ids[i] = rb_to_id(vid);
567
+ data->stype[i] = *ctype;
568
+ ctype ++;
569
+ if (isdigit(*ctype)) {
570
+ char *p, *d;
571
+ for (p=ctype; isdigit(*p); p++) ;
572
+ d = ALLOCA_N(char, p - ctype + 1);
573
+ strncpy(d, ctype, p - ctype);
574
+ d[p - ctype] = '\0';
575
+ data->ssize[i] = atoi(d);
576
+ ctype = p;
577
+ }
578
+ else{
579
+ data->ssize[i] = 1;
580
+ }
581
+ }
582
+
583
+ if (*ctype) {
584
+ rb_raise(rb_eArgError, "too few/many arguments");
585
+ }
586
+
587
+ if (!data->size)
588
+ data->size = dlsizeof(RSTRING(type)->ptr);
589
+
590
+ return Qnil;
591
+ }
592
+
593
+ VALUE
594
+ rb_dlptr_define_struct(int argc, VALUE argv[], VALUE self)
595
+ {
596
+ VALUE *pass_argv;
597
+ int pass_argc, i;
598
+
599
+ pass_argc = argc + 1;
600
+ pass_argv = ALLOCA_N(VALUE, pass_argc);
601
+ pass_argv[0] = INT2FIX(DLPTR_CTYPE_STRUCT);
602
+ for (i=1; i<pass_argc; i++) {
603
+ pass_argv[i] = argv[i-1];
604
+ }
605
+ return rb_dlptr_define_data_type(pass_argc, pass_argv, self);
606
+ }
607
+
608
+ VALUE
609
+ rb_dlptr_define_union(int argc, VALUE argv[], VALUE self)
610
+ {
611
+ VALUE *pass_argv;
612
+ int pass_argc, i;
613
+
614
+ pass_argc = argc + 1;
615
+ pass_argv = ALLOCA_N(VALUE, pass_argc);
616
+ pass_argv[0] = INT2FIX(DLPTR_CTYPE_UNION);
617
+ for (i=1; i<pass_argc; i++) {
618
+ pass_argv[i] = argv[i-1];
619
+ }
620
+ return rb_dlptr_define_data_type(pass_argc, pass_argv, self);
621
+ }
622
+
623
+ VALUE
624
+ rb_dlptr_get_data_type(VALUE self)
625
+ {
626
+ struct ptr_data *data;
627
+
628
+ Data_Get_Struct(self, struct ptr_data, data);
629
+ if (data->stype)
630
+ return rb_assoc_new(INT2FIX(data->ctype),
631
+ rb_tainted_str_new(data->stype, data->slen));
632
+ else
633
+ return rb_assoc_new(INT2FIX(data->ctype), Qnil);
634
+ }
635
+
636
+ static VALUE
637
+ cary2ary(void *ptr, char t, int len)
638
+ {
639
+ VALUE ary;
640
+ VALUE elem;
641
+ int i;
642
+
643
+ if (len < 1)
644
+ return Qnil;
645
+
646
+ if (len == 1) {
647
+ switch (t) {
648
+ case 'I':
649
+ elem = INT2NUM(*((int*)ptr));
650
+ ptr = (char *)ptr + sizeof(int);
651
+ break;
652
+ case 'L':
653
+ elem = DLLONG2NUM(*((long*)ptr));
654
+ ptr = (char *)ptr + sizeof(long);
655
+ break;
656
+ case 'P':
657
+ case 'S':
658
+ elem = rb_dlptr_new(*((void**)ptr),0, 0);
659
+ ptr = (char *)ptr + sizeof(void*);
660
+ break;
661
+ case 'F':
662
+ elem = rb_float_new(*((float*)ptr));
663
+ ptr = (char *)ptr + sizeof(float);
664
+ break;
665
+ case 'D':
666
+ elem = rb_float_new(*((double*)ptr));
667
+ ptr = (char *)ptr + sizeof(double);
668
+ break;
669
+ case 'C':
670
+ elem = INT2NUM(*((char*)ptr));
671
+ ptr = (char *)ptr + sizeof(char);
672
+ break;
673
+ case 'H':
674
+ elem = INT2NUM(*((short*)ptr));
675
+ ptr = (char *)ptr + sizeof(short);
676
+ break;
677
+ default:
678
+ rb_raise(rb_eDLTypeError, "unsupported type '%c'", t);
679
+ }
680
+ return elem;
681
+ }
682
+
683
+ ary = rb_ary_new();
684
+ for (i=0; i < len; i++) {
685
+ switch (t) {
686
+ case 'I':
687
+ elem = INT2NUM(*((int*)ptr));
688
+ ptr = (char *)ptr + sizeof(int);
689
+ break;
690
+ case 'L':
691
+ elem = DLLONG2NUM(*((long*)ptr));
692
+ ptr = (char *)ptr + sizeof(long);
693
+ break;
694
+ case 'P':
695
+ case 'S':
696
+ elem = rb_dlptr_new(*((void**)ptr), 0, 0);
697
+ ptr = (char *)ptr + sizeof(void*);
698
+ break;
699
+ case 'F':
700
+ elem = rb_float_new(*((float*)ptr));
701
+ ptr = (char *)ptr + sizeof(float);
702
+ break;
703
+ case 'D':
704
+ elem = rb_float_new(*((float*)ptr));
705
+ ptr = (char *)ptr + sizeof(double);
706
+ break;
707
+ case 'C':
708
+ elem = INT2NUM(*((char*)ptr));
709
+ ptr = (char *)ptr + sizeof(char);
710
+ break;
711
+ case 'H':
712
+ elem = INT2NUM(*((short*)ptr));
713
+ ptr = (char *)ptr + sizeof(short);
714
+ break;
715
+ default:
716
+ rb_raise(rb_eDLTypeError, "unsupported type '%c'", t);
717
+ }
718
+ rb_ary_push(ary, elem);
719
+ }
720
+
721
+ return ary;
722
+ }
723
+
724
+ VALUE
725
+ rb_dlptr_aref(int argc, VALUE argv[], VALUE self)
726
+ {
727
+ VALUE key = Qnil, num = Qnil;
728
+ ID id;
729
+ struct ptr_data *data;
730
+ int i;
731
+ int offset;
732
+
733
+ if (rb_scan_args(argc, argv, "11", &key, &num) == 1) {
734
+ num = INT2NUM(0);
735
+ }
736
+
737
+ if (TYPE(key) == T_FIXNUM || TYPE(key) == T_BIGNUM) {
738
+ VALUE pass[1];
739
+ pass[0] = num;
740
+ return rb_dlptr_to_str(1, pass, rb_dlptr_plus(self, key));
741
+ }
742
+ rb_to_id(key);
743
+ if (! (TYPE(key) == T_STRING || TYPE(key) == T_SYMBOL)) {
744
+ rb_raise(rb_eTypeError, "the key must be a string or symbol");
745
+ }
746
+
747
+ id = rb_to_id(key);
748
+ Data_Get_Struct(self, struct ptr_data, data);
749
+ offset = 0;
750
+ switch (data->ctype) {
751
+ case DLPTR_CTYPE_STRUCT:
752
+ for (i=0; i < data->ids_num; i++) {
753
+ switch (data->stype[i]) {
754
+ case 'I':
755
+ DLALIGN(data->ptr,offset,INT_ALIGN);
756
+ break;
757
+ case 'L':
758
+ DLALIGN(data->ptr,offset,LONG_ALIGN);
759
+ break;
760
+ case 'P':
761
+ case 'S':
762
+ DLALIGN(data->ptr,offset,VOIDP_ALIGN);
763
+ break;
764
+ case 'F':
765
+ DLALIGN(data->ptr,offset,FLOAT_ALIGN);
766
+ break;
767
+ case 'D':
768
+ DLALIGN(data->ptr,offset,DOUBLE_ALIGN);
769
+ break;
770
+ case 'C':
771
+ break;
772
+ case 'H':
773
+ DLALIGN(data->ptr,offset,SHORT_ALIGN);
774
+ break;
775
+ default:
776
+ rb_raise(rb_eDLTypeError, "unsupported type '%c'", data->stype[i]);
777
+ }
778
+ if (data->ids[i] == id) {
779
+ return cary2ary((char *)data->ptr + offset, data->stype[i], data->ssize[i]);
780
+ }
781
+ switch (data->stype[i]) {
782
+ case 'I':
783
+ offset += sizeof(int) * data->ssize[i];
784
+ break;
785
+ case 'L':
786
+ offset += sizeof(long) * data->ssize[i];
787
+ break;
788
+ case 'P':
789
+ case 'S':
790
+ offset += sizeof(void*) * data->ssize[i];
791
+ break;
792
+ case 'F':
793
+ offset += sizeof(float) * data->ssize[i];
794
+ break;
795
+ case 'D':
796
+ offset += sizeof(double) * data->ssize[i];
797
+ break;
798
+ case 'C':
799
+ offset += sizeof(char) * data->ssize[i];
800
+ break;
801
+ case 'H':
802
+ offset += sizeof(short) * data->ssize[i];
803
+ break;
804
+ default:
805
+ rb_raise(rb_eDLTypeError, "unsupported type '%c'", data->stype[i]);
806
+ }
807
+ }
808
+ break;
809
+ case DLPTR_CTYPE_UNION:
810
+ for (i=0; i < data->ids_num; i++) {
811
+ if (data->ids[i] == id) {
812
+ return cary2ary((char *)data->ptr + offset, data->stype[i], data->ssize[i]);
813
+ }
814
+ }
815
+ break;
816
+ } /* end of switch */
817
+
818
+ rb_raise(rb_eNameError, "undefined key `%s' for %s",
819
+ rb_id2name(id), rb_class2name(CLASS_OF(self)));
820
+
821
+ return Qnil;
822
+ }
823
+
824
+ static void *
825
+ ary2cary(char t, VALUE val, long *size)
826
+ {
827
+ void *ptr;
828
+
829
+ if (TYPE(val) == T_ARRAY) {
830
+ ptr = rb_ary2cary(t, val, size);
831
+ }
832
+ else{
833
+ ptr = rb_ary2cary(t, rb_ary_new3(1, val), size);
834
+ }
835
+ return ptr;
836
+ }
837
+
838
+ VALUE
839
+ rb_dlptr_aset(int argc, VALUE argv[], VALUE self)
840
+ {
841
+ VALUE key = Qnil, num = Qnil, val = Qnil;
842
+ ID id;
843
+ struct ptr_data *data;
844
+ int i;
845
+ int offset;
846
+ long memsize;
847
+ void *memimg;
848
+
849
+ rb_secure(4);
850
+ switch (rb_scan_args(argc, argv, "21", &key, &num, &val)) {
851
+ case 2:
852
+ val = num;
853
+ num = Qnil;
854
+ break;
855
+ }
856
+
857
+ if (TYPE(key) == T_FIXNUM || TYPE(key) == T_BIGNUM) {
858
+ void *dst, *src;
859
+ long len;
860
+
861
+ StringValue(val);
862
+ Data_Get_Struct(self, struct ptr_data, data);
863
+ dst = (void*)((long)(data->ptr) + DLNUM2LONG(key));
864
+ src = RSTRING(val)->ptr;
865
+ len = RSTRING(val)->len;
866
+ if (num == Qnil) {
867
+ memcpy(dst, src, len);
868
+ }
869
+ else{
870
+ long n = NUM2INT(num);
871
+ memcpy(dst, src, n < len ? n : len);
872
+ if (n > len) MEMZERO((char*)dst + len, char, n - len);
873
+ }
874
+ return val;
875
+ }
876
+
877
+ id = rb_to_id(key);
878
+ Data_Get_Struct(self, struct ptr_data, data);
879
+ switch (data->ctype) {
880
+ case DLPTR_CTYPE_STRUCT:
881
+ offset = 0;
882
+ for (i=0; i < data->ids_num; i++) {
883
+ switch (data->stype[i]) {
884
+ case 'I':
885
+ DLALIGN(data->ptr,offset,INT_ALIGN);
886
+ break;
887
+ case 'L':
888
+ DLALIGN(data->ptr,offset,LONG_ALIGN);
889
+ break;
890
+ case 'P':
891
+ case 'S':
892
+ DLALIGN(data->ptr,offset,VOIDP_ALIGN);
893
+ break;
894
+ case 'D':
895
+ DLALIGN(data->ptr,offset,DOUBLE_ALIGN);
896
+ break;
897
+ case 'F':
898
+ DLALIGN(data->ptr,offset,FLOAT_ALIGN);
899
+ break;
900
+ case 'C':
901
+ break;
902
+ case 'H':
903
+ DLALIGN(data->ptr,offset,SHORT_ALIGN);
904
+ break;
905
+ default:
906
+ rb_raise(rb_eDLTypeError, "unsupported type '%c'", data->stype[i]);
907
+ }
908
+ if (data->ids[i] == id) {
909
+ memimg = ary2cary(data->stype[i], val, &memsize);
910
+ memcpy((char *)data->ptr + offset, memimg, memsize);
911
+ dlfree(memimg);
912
+ return val;
913
+ }
914
+ switch (data->stype[i]) {
915
+ case 'I':
916
+ case 'i':
917
+ offset += sizeof(int) * data->ssize[i];
918
+ break;
919
+ case 'L':
920
+ case 'l':
921
+ offset += sizeof(long) * data->ssize[i];
922
+ break;
923
+ case 'P':
924
+ case 'p':
925
+ case 'S':
926
+ case 's':
927
+ offset += sizeof(void*) * data->ssize[i];
928
+ break;
929
+ case 'D':
930
+ case 'd':
931
+ offset += sizeof(double) * data->ssize[i];
932
+ break;
933
+ case 'F':
934
+ case 'f':
935
+ offset += sizeof(float) * data->ssize[i];
936
+ break;
937
+ case 'C':
938
+ case 'c':
939
+ offset += sizeof(char) * data->ssize[i];
940
+ break;
941
+ case 'H':
942
+ case 'h':
943
+ offset += sizeof(short) * data->ssize[i];
944
+ break;
945
+ default:
946
+ rb_raise(rb_eDLTypeError, "unsupported type '%c'", data->stype[i]);
947
+ }
948
+ }
949
+ return val;
950
+ /* break; */
951
+ case DLPTR_CTYPE_UNION:
952
+ for (i=0; i < data->ids_num; i++) {
953
+ if (data->ids[i] == id) {
954
+ switch (data->stype[i]) {
955
+ case 'I': case 'i':
956
+ memsize = sizeof(int) * data->ssize[i];
957
+ break;
958
+ case 'L': case 'l':
959
+ memsize = sizeof(long) * data->ssize[i];
960
+ break;
961
+ case 'P': case 'p':
962
+ case 'S': case 's':
963
+ memsize = sizeof(void*) * data->ssize[i];
964
+ break;
965
+ case 'F': case 'f':
966
+ memsize = sizeof(float) * data->ssize[i];
967
+ break;
968
+ case 'D': case 'd':
969
+ memsize = sizeof(double) * data->ssize[i];
970
+ break;
971
+ case 'C': case 'c':
972
+ memsize = sizeof(char) * data->ssize[i];
973
+ break;
974
+ case 'H': case 'h':
975
+ memsize = sizeof(short) * data->ssize[i];
976
+ break;
977
+ default:
978
+ rb_raise(rb_eDLTypeError, "unsupported type '%c'", data->stype[i]);
979
+ }
980
+ memimg = ary2cary(data->stype[i], val, NULL);
981
+ memcpy(data->ptr, memimg, memsize);
982
+ dlfree(memimg);
983
+ }
984
+ }
985
+ return val;
986
+ /* break; */
987
+ }
988
+
989
+ rb_raise(rb_eNameError, "undefined key `%s' for %s",
990
+ rb_id2name(id), rb_class2name(CLASS_OF(self)));
991
+
992
+ return Qnil;
993
+ }
994
+
995
+ VALUE
996
+ rb_dlptr_size(int argc, VALUE argv[], VALUE self)
997
+ {
998
+ VALUE size;
999
+
1000
+ if (rb_scan_args(argc, argv, "01", &size) == 0){
1001
+ return DLLONG2NUM(RDLPTR(self)->size);
1002
+ }
1003
+ else{
1004
+ RDLPTR(self)->size = DLNUM2LONG(size);
1005
+ return size;
1006
+ }
1007
+ }
1008
+
1009
+ static int
1010
+ dlmem_each_i(void* key, VALUE value, void* arg)
1011
+ {
1012
+ VALUE vkey = DLLONG2NUM(key);
1013
+ rb_yield(rb_assoc_new(vkey, value));
1014
+ return Qnil;
1015
+ }
1016
+
1017
+ VALUE
1018
+ rb_dlmem_each(VALUE self)
1019
+ {
1020
+ st_foreach(st_memory_table, dlmem_each_i, 0);
1021
+ return Qnil;
1022
+ }
1023
+
1024
+ void
1025
+ Init_dlptr()
1026
+ {
1027
+ rb_cDLPtrData = rb_define_class_under(rb_mDL, "PtrData", rb_cObject);
1028
+ rb_define_alloc_func(rb_cDLPtrData, rb_dlptr_s_allocate);
1029
+ rb_define_singleton_method(rb_cDLPtrData, "malloc", rb_dlptr_s_malloc, -1);
1030
+ rb_define_method(rb_cDLPtrData, "initialize", rb_dlptr_initialize, -1);
1031
+ rb_define_method(rb_cDLPtrData, "free=", rb_dlptr_free_set, 1);
1032
+ rb_define_method(rb_cDLPtrData, "free", rb_dlptr_free_get, 0);
1033
+ rb_define_method(rb_cDLPtrData, "to_i", rb_dlptr_to_i, 0);
1034
+ rb_define_method(rb_cDLPtrData, "ptr", rb_dlptr_ptr, 0);
1035
+ rb_define_method(rb_cDLPtrData, "+@", rb_dlptr_ptr, 0);
1036
+ rb_define_method(rb_cDLPtrData, "ref", rb_dlptr_ref, 0);
1037
+ rb_define_method(rb_cDLPtrData, "-@", rb_dlptr_ref, 0);
1038
+ rb_define_method(rb_cDLPtrData, "null?", rb_dlptr_null_p, 0);
1039
+ rb_define_method(rb_cDLPtrData, "to_a", rb_dlptr_to_array, -1);
1040
+ rb_define_method(rb_cDLPtrData, "to_s", rb_dlptr_to_s, -1);
1041
+ rb_define_method(rb_cDLPtrData, "to_str", rb_dlptr_to_str, -1);
1042
+ rb_define_method(rb_cDLPtrData, "inspect", rb_dlptr_inspect, 0);
1043
+ rb_define_method(rb_cDLPtrData, "<=>", rb_dlptr_cmp, 1);
1044
+ rb_define_method(rb_cDLPtrData, "==", rb_dlptr_eql, 1);
1045
+ rb_define_method(rb_cDLPtrData, "eql?", rb_dlptr_eql, 1);
1046
+ rb_define_method(rb_cDLPtrData, "+", rb_dlptr_plus, 1);
1047
+ rb_define_method(rb_cDLPtrData, "-", rb_dlptr_minus, 1);
1048
+ rb_define_method(rb_cDLPtrData, "define_data_type",
1049
+ rb_dlptr_define_data_type, -1);
1050
+ rb_define_method(rb_cDLPtrData, "struct!", rb_dlptr_define_struct, -1);
1051
+ rb_define_method(rb_cDLPtrData, "union!", rb_dlptr_define_union, -1);
1052
+ rb_define_method(rb_cDLPtrData, "data_type", rb_dlptr_get_data_type, 0);
1053
+ rb_define_method(rb_cDLPtrData, "[]", rb_dlptr_aref, -1);
1054
+ rb_define_method(rb_cDLPtrData, "[]=", rb_dlptr_aset, -1);
1055
+ rb_define_method(rb_cDLPtrData, "size", rb_dlptr_size, -1);
1056
+ rb_define_method(rb_cDLPtrData, "size=", rb_dlptr_size, -1);
1057
+
1058
+ rb_mDLMemorySpace = rb_define_module_under(rb_mDL, "MemorySpace");
1059
+ st_memory_table = st_init_numtable();
1060
+ rb_define_const(rb_mDLMemorySpace, "MemoryTable", Qnil); /* historical */
1061
+ rb_define_module_function(rb_mDLMemorySpace, "each", rb_dlmem_each, 0);
1062
+ }