11 static ID id_last_error
;
14 rb_dl_get_last_error(VALUE self
)
16 return rb_thread_local_aref(rb_thread_current(), id_last_error
);
20 rb_dl_set_last_error(VALUE self
, VALUE val
)
22 rb_thread_local_aset(rb_thread_current(), id_last_error
, val
);
26 #if defined(HAVE_WINDOWS_H)
28 static ID id_win32_last_error
;
31 rb_dl_get_win32_last_error(VALUE self
)
33 return rb_thread_local_aref(rb_thread_current(), id_win32_last_error
);
37 rb_dl_set_win32_last_error(VALUE self
, VALUE val
)
39 rb_thread_local_aset(rb_thread_current(), id_win32_last_error
, val
);
46 dlcfunc_free(struct cfunc_data
*data
)
55 rb_dlcfunc_new(void (*func
)(), int type
, const char *name
, ID calltype
)
58 struct cfunc_data
*data
;
62 val
= Data_Make_Struct(rb_cDLCFunc
, struct cfunc_data
, 0, dlcfunc_free
, data
);
64 data
->name
= name
? strdup(name
) : NULL
;
66 data
->calltype
= calltype
;
76 rb_dlcfunc2ptr(VALUE val
)
78 struct cfunc_data
*data
;
81 if( rb_obj_is_kind_of(val
, rb_cDLCFunc
) ){
82 Data_Get_Struct(val
, struct cfunc_data
, data
);
85 else if( val
== Qnil
){
89 rb_raise(rb_eTypeError
, "DL::CFunc was expected");
96 rb_dlcfunc_s_allocate(VALUE klass
)
99 struct cfunc_data
*data
;
101 obj
= Data_Make_Struct(klass
, struct cfunc_data
, 0, dlcfunc_free
, data
);
105 data
->calltype
= CFUNC_CDECL
;
111 rb_dlcfunc_initialize(int argc
, VALUE argv
[], VALUE self
)
113 VALUE addr
, name
, type
, calltype
;
114 struct cfunc_data
*data
;
118 rb_scan_args(argc
, argv
, "13", &addr
, &type
, &name
, &calltype
);
120 saddr
= (void*)(NUM2PTR(rb_Integer(addr
)));
121 sname
= NIL_P(name
) ? NULL
: StringValuePtr(name
);
123 Data_Get_Struct(self
, struct cfunc_data
, data
);
124 if( data
->name
) xfree(data
->name
);
126 data
->name
= sname
? strdup(sname
) : 0;
127 data
->type
= (type
== Qnil
) ? DLTYPE_VOID
: NUM2INT(type
);
128 data
->calltype
= (calltype
== Qnil
) ? CFUNC_CDECL
: SYM2ID(calltype
);
134 rb_dlcfunc_name(VALUE self
)
136 struct cfunc_data
*cfunc
;
138 Data_Get_Struct(self
, struct cfunc_data
, cfunc
);
139 return cfunc
->name
? rb_tainted_str_new2(cfunc
->name
) : Qnil
;
143 rb_dlcfunc_ctype(VALUE self
)
145 struct cfunc_data
*cfunc
;
147 Data_Get_Struct(self
, struct cfunc_data
, cfunc
);
148 return INT2NUM(cfunc
->type
);
152 rb_dlcfunc_set_ctype(VALUE self
, VALUE ctype
)
154 struct cfunc_data
*cfunc
;
156 Data_Get_Struct(self
, struct cfunc_data
, cfunc
);
157 cfunc
->type
= NUM2INT(ctype
);
162 rb_dlcfunc_calltype(VALUE self
)
164 struct cfunc_data
*cfunc
;
166 Data_Get_Struct(self
, struct cfunc_data
, cfunc
);
167 return ID2SYM(cfunc
->calltype
);
171 rb_dlcfunc_set_calltype(VALUE self
, VALUE sym
)
173 struct cfunc_data
*cfunc
;
175 Data_Get_Struct(self
, struct cfunc_data
, cfunc
);
176 cfunc
->calltype
= SYM2ID(sym
);
182 rb_dlcfunc_ptr(VALUE self
)
184 struct cfunc_data
*cfunc
;
186 Data_Get_Struct(self
, struct cfunc_data
, cfunc
);
187 return PTR2NUM(cfunc
->ptr
);
191 rb_dlcfunc_set_ptr(VALUE self
, VALUE addr
)
193 struct cfunc_data
*cfunc
;
195 Data_Get_Struct(self
, struct cfunc_data
, cfunc
);
196 cfunc
->ptr
= NUM2PTR(addr
);
202 rb_dlcfunc_inspect(VALUE self
)
207 struct cfunc_data
*cfunc
;
209 Data_Get_Struct(self
, struct cfunc_data
, cfunc
);
211 str_size
= (cfunc
->name
? strlen(cfunc
->name
) : 0) + 100;
212 str
= ruby_xmalloc(str_size
);
213 snprintf(str
, str_size
- 1,
214 "#<DL::CFunc:%p ptr=%p type=%d name='%s'>",
218 cfunc
->name
? cfunc
->name
: "");
219 val
= rb_tainted_str_new2(str
);
226 # define DECL_FUNC_CDECL(f,ret,args) ret (FUNC_CDECL(*f))(args)
227 # define DECL_FUNC_STDCALL(f,ret,args) ret (FUNC_STDCALL(*f))(args)
229 #define CALL_CASE switch( RARRAY_LEN(ary) ){ \
231 CASE(1); break; CASE(2); break; CASE(3); break; CASE(4); break; CASE(5); break; \
232 CASE(6); break; CASE(7); break; CASE(8); break; CASE(9); break; CASE(10);break; \
233 CASE(11);break; CASE(12);break; CASE(13);break; CASE(14);break; CASE(15);break; \
234 CASE(16);break; CASE(17);break; CASE(18);break; CASE(19);break; CASE(20);break; \
235 default: rb_raise(rb_eArgError, "too many arguments"); \
240 rb_dlcfunc_call(VALUE self
, VALUE ary
)
242 struct cfunc_data
*cfunc
;
244 DLSTACK_TYPE stack
[DLSTACK_SIZE
];
247 rb_secure_update(self
);
249 memset(stack
, 0, sizeof(DLSTACK_TYPE
) * DLSTACK_SIZE
);
250 Check_Type(ary
, T_ARRAY
);
252 Data_Get_Struct(self
, struct cfunc_data
, cfunc
);
254 if( cfunc
->ptr
== 0 ){
255 rb_raise(rb_eDLError
, "can't call null-function");
259 for( i
= 0; i
< RARRAY_LEN(ary
); i
++ ){
260 if( i
>= DLSTACK_SIZE
){
261 rb_raise(rb_eDLError
, "too many arguments (stack overflow)");
263 stack
[i
] = NUM2LONG(RARRAY_PTR(ary
)[i
]);
266 /* calltype == CFUNC_CDECL */
267 if( cfunc
->calltype
== CFUNC_CDECL
){
268 switch( cfunc
->type
){
270 #define CASE(n) case n: { \
271 DECL_FUNC_CDECL(f,void,DLSTACK_PROTO##n) = cfunc->ptr; \
272 f(DLSTACK_ARGS##n(stack)); \
279 #define CASE(n) case n: { \
280 DECL_FUNC_CDECL(f,void*,DLSTACK_PROTO##n) = cfunc->ptr; \
282 ret = f(DLSTACK_ARGS##n(stack)); \
283 result = PTR2NUM(ret); \
289 #define CASE(n) case n: { \
290 DECL_FUNC_CDECL(f,char,DLSTACK_PROTO##n) = cfunc->ptr; \
292 ret = f(DLSTACK_ARGS##n(stack)); \
293 result = CHR2FIX(ret); \
299 #define CASE(n) case n: { \
300 DECL_FUNC_CDECL(f,short,DLSTACK_PROTO##n) = cfunc->ptr; \
302 ret = f(DLSTACK_ARGS##n(stack)); \
303 result = INT2NUM((int)ret); \
309 #define CASE(n) case n: { \
310 DECL_FUNC_CDECL(f,int,DLSTACK_PROTO##n) = cfunc->ptr; \
312 ret = f(DLSTACK_ARGS##n(stack)); \
313 result = INT2NUM(ret); \
319 #define CASE(n) case n: { \
320 DECL_FUNC_CDECL(f,long,DLSTACK_PROTO##n) = cfunc->ptr; \
322 ret = f(DLSTACK_ARGS##n(stack)); \
323 result = LONG2NUM(ret); \
328 #if HAVE_LONG_LONG /* used in ruby.h */
329 case DLTYPE_LONG_LONG
:
330 #define CASE(n) case n: { \
331 DECL_FUNC_CDECL(f,LONG_LONG,DLSTACK_PROTO) = cfunc->ptr; \
333 ret = f(DLSTACK_ARGS(stack)); \
334 result = LL2NUM(ret); \
341 #define CASE(n) case n: { \
342 DECL_FUNC_CDECL(f,float,DLSTACK_PROTO) = cfunc->ptr; \
344 ret = f(DLSTACK_ARGS(stack)); \
345 result = rb_float_new(ret); \
351 #define CASE(n) case n: { \
352 DECL_FUNC_CDECL(f,double,DLSTACK_PROTO) = cfunc->ptr; \
354 ret = f(DLSTACK_ARGS(stack)); \
355 result = rb_float_new(ret); \
361 rb_raise(rb_eDLTypeError
, "unknown type %d", cfunc
->type
);
364 else if( cfunc
->calltype
== CFUNC_STDCALL
){
365 /* calltype == CFUNC_STDCALL */
366 switch( cfunc
->type
){
368 #define CASE(n) case n: { \
369 DECL_FUNC_STDCALL(f,void,DLSTACK_PROTO##n) = cfunc->ptr; \
370 f(DLSTACK_ARGS##n(stack)); \
377 #define CASE(n) case n: { \
378 DECL_FUNC_STDCALL(f,void*,DLSTACK_PROTO##n) = cfunc->ptr; \
380 ret = f(DLSTACK_ARGS##n(stack)); \
381 result = PTR2NUM(ret); \
387 #define CASE(n) case n: { \
388 DECL_FUNC_STDCALL(f,char,DLSTACK_PROTO##n) = cfunc->ptr; \
390 ret = f(DLSTACK_ARGS##n(stack)); \
391 result = CHR2FIX(ret); \
397 #define CASE(n) case n: { \
398 DECL_FUNC_STDCALL(f,short,DLSTACK_PROTO##n) = cfunc->ptr; \
400 ret = f(DLSTACK_ARGS##n(stack)); \
401 result = INT2NUM((int)ret); \
407 #define CASE(n) case n: { \
408 DECL_FUNC_STDCALL(f,int,DLSTACK_PROTO##n) = cfunc->ptr; \
410 ret = f(DLSTACK_ARGS##n(stack)); \
411 result = INT2NUM(ret); \
417 #define CASE(n) case n: { \
418 DECL_FUNC_STDCALL(f,long,DLSTACK_PROTO##n) = cfunc->ptr; \
420 ret = f(DLSTACK_ARGS##n(stack)); \
421 result = LONG2NUM(ret); \
426 #if HAVE_LONG_LONG /* used in ruby.h */
427 case DLTYPE_LONG_LONG
:
428 #define CASE(n) case n: { \
429 DECL_FUNC_STDCALL(f,LONG_LONG,DLSTACK_PROTO) = cfunc->ptr; \
431 ret = f(DLSTACK_ARGS(stack)); \
432 result = LL2NUM(ret); \
439 #define CASE(n) case n: { \
440 DECL_FUNC_STDCALL(f,float,DLSTACK_PROTO) = cfunc->ptr; \
442 ret = f(DLSTACK_ARGS(stack)); \
443 result = rb_float_new(ret); \
449 #define CASE(n) case n: { \
450 DECL_FUNC_STDCALL(f,double,DLSTACK_PROTO) = cfunc->ptr; \
452 ret = f(DLSTACK_ARGS(stack)); \
453 result = rb_float_new(ret); \
459 rb_raise(rb_eDLTypeError
, "unknown type %d", cfunc
->type
);
463 rb_raise(rb_eDLError
,
464 #ifndef LONG_LONG_VALUE
465 "unsupported call type: %lx",
467 "unsupported call type: %llx",
472 rb_dl_set_last_error(self
, INT2NUM(errno
));
473 #if defined(HAVE_WINDOWS_H)
474 rb_dl_set_win32_last_error(self
, INT2NUM(GetLastError()));
481 rb_dlcfunc_to_i(VALUE self
)
483 struct cfunc_data
*cfunc
;
485 Data_Get_Struct(self
, struct cfunc_data
, cfunc
);
486 return PTR2NUM(cfunc
->ptr
);
492 id_last_error
= rb_intern("__DL2_LAST_ERROR__");
493 #if defined(HAVE_WINDOWS_H)
494 id_win32_last_error
= rb_intern("__DL2_WIN32_LAST_ERROR__");
496 rb_cDLCFunc
= rb_define_class_under(rb_mDL
, "CFunc", rb_cObject
);
497 rb_define_alloc_func(rb_cDLCFunc
, rb_dlcfunc_s_allocate
);
498 rb_define_module_function(rb_cDLCFunc
, "last_error", rb_dl_get_last_error
, 0);
499 #if defined(HAVE_WINDOWS_H)
500 rb_define_module_function(rb_cDLCFunc
, "win32_last_error", rb_dl_get_win32_last_error
, 0);
502 rb_define_method(rb_cDLCFunc
, "initialize", rb_dlcfunc_initialize
, -1);
503 rb_define_method(rb_cDLCFunc
, "call", rb_dlcfunc_call
, 1);
504 rb_define_method(rb_cDLCFunc
, "[]", rb_dlcfunc_call
, 1);
505 rb_define_method(rb_cDLCFunc
, "name", rb_dlcfunc_name
, 0);
506 rb_define_method(rb_cDLCFunc
, "ctype", rb_dlcfunc_ctype
, 0);
507 rb_define_method(rb_cDLCFunc
, "ctype=", rb_dlcfunc_set_ctype
, 1);
508 rb_define_method(rb_cDLCFunc
, "calltype", rb_dlcfunc_calltype
, 0);
509 rb_define_method(rb_cDLCFunc
, "calltype=", rb_dlcfunc_set_calltype
, 1);
510 rb_define_method(rb_cDLCFunc
, "ptr", rb_dlcfunc_ptr
, 0);
511 rb_define_method(rb_cDLCFunc
, "ptr=", rb_dlcfunc_set_ptr
, 1);
512 rb_define_method(rb_cDLCFunc
, "inspect", rb_dlcfunc_inspect
, 0);
513 rb_define_method(rb_cDLCFunc
, "to_s", rb_dlcfunc_inspect
, 0);
514 rb_define_method(rb_cDLCFunc
, "to_i", rb_dlcfunc_to_i
, 0);