rubysl-dl 0.0.1 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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
+ }