* ext/dl: change the callback mechanism.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@2532 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
d5ceb6ef82
commit
2d5b7f7365
@ -1,3 +1,7 @@
|
|||||||
|
Sun Jun 9 17:40:41 2002 Takaaki Tateishi <ttate@kt.jaist.ac.jp>
|
||||||
|
|
||||||
|
* ext/dl: change the callback mechanism.
|
||||||
|
|
||||||
Thu Jun 6 19:50:39 2002 KONISHI Hiromasa <H_Konishi@ruby-lang.org>
|
Thu Jun 6 19:50:39 2002 KONISHI Hiromasa <H_Konishi@ruby-lang.org>
|
||||||
|
|
||||||
* sample/biorhythm.rb (getPosiiton,etc)
|
* sample/biorhythm.rb (getPosiiton,etc)
|
||||||
|
250
ext/dl/dl.c
250
ext/dl/dl.c
@ -11,9 +11,95 @@ VALUE rb_eDLError;
|
|||||||
VALUE rb_eDLTypeError;
|
VALUE rb_eDLTypeError;
|
||||||
|
|
||||||
static VALUE DLFuncTable;
|
static VALUE DLFuncTable;
|
||||||
static void *rb_dl_func_table[MAX_CALLBACK_TYPE][MAX_CALLBACK];
|
static void *rb_dl_callback_table[CALLBACK_TYPES][MAX_CALLBACK];
|
||||||
static ID id_call;
|
static ID id_call;
|
||||||
|
|
||||||
|
static int
|
||||||
|
rb_dl_scan_callback_args(long stack[], const char *proto,
|
||||||
|
int *argc, VALUE (*argv)[])
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
long *sp;
|
||||||
|
VALUE val;
|
||||||
|
|
||||||
|
sp = stack;
|
||||||
|
for( i=1; proto[i]; i++ ){
|
||||||
|
switch( proto[i] ){
|
||||||
|
case 'C':
|
||||||
|
{
|
||||||
|
char v;
|
||||||
|
memcpy(&v, sp, sizeof(long));
|
||||||
|
sp++;
|
||||||
|
val = INT2NUM(v);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'H':
|
||||||
|
{
|
||||||
|
short v;
|
||||||
|
memcpy(&v, sp, sizeof(long));
|
||||||
|
sp++;
|
||||||
|
val = INT2NUM(v);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'I':
|
||||||
|
{
|
||||||
|
int v;
|
||||||
|
memcpy(&v, sp, sizeof(long));
|
||||||
|
sp++;
|
||||||
|
val = INT2NUM(v);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'L':
|
||||||
|
{
|
||||||
|
long v;
|
||||||
|
memcpy(&v, sp, sizeof(long));
|
||||||
|
sp++;
|
||||||
|
val = INT2NUM(v);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'F':
|
||||||
|
{
|
||||||
|
float v;
|
||||||
|
memcpy(&v, sp, sizeof(float));
|
||||||
|
sp += sizeof(float)/sizeof(long);
|
||||||
|
val = rb_float_new(v);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'D':
|
||||||
|
{
|
||||||
|
double v;
|
||||||
|
memcpy(&v, sp, sizeof(double));
|
||||||
|
sp += sizeof(double)/sizeof(long);
|
||||||
|
val = rb_float_new(v);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'P':
|
||||||
|
{
|
||||||
|
void *v;
|
||||||
|
memcpy(&v, sp, sizeof(void*));
|
||||||
|
sp++;
|
||||||
|
val = rb_dlptr_new(v, 0, 0);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'S':
|
||||||
|
{
|
||||||
|
char *v;
|
||||||
|
memcpy(&v, sp, sizeof(void*));
|
||||||
|
sp++;
|
||||||
|
val = rb_tainted_str_new2(v);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
rb_raise(rb_eDLTypeError, "unsupported type `%c'", proto[i]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
(*argv)[i-1] = val;
|
||||||
|
}
|
||||||
|
*argc = (i - 1);
|
||||||
|
|
||||||
|
return (*argc);
|
||||||
|
}
|
||||||
|
|
||||||
#include "callback.func"
|
#include "callback.func"
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -476,121 +562,88 @@ rb_dl_sizeof(VALUE self, VALUE str)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static VALUE
|
static VALUE
|
||||||
rb_dl_callback_type(VALUE *str)
|
rb_dl_callback(int argc, VALUE argv[], VALUE self)
|
||||||
{
|
{
|
||||||
char *type;
|
VALUE type, proc;
|
||||||
int len;
|
int rettype, entry, i;
|
||||||
int i;
|
char fname[127];
|
||||||
long ftype;
|
|
||||||
|
|
||||||
ftype = 0;
|
proc = Qnil;
|
||||||
type = StringValuePtr(*str);
|
switch( rb_scan_args(argc, argv, "11", &type, &proc) ){
|
||||||
len = RSTRING(*str)->len;
|
case 1:
|
||||||
|
if( rb_block_given_p() ){
|
||||||
if( len - 1 > MAX_CBARG ){
|
proc = rb_f_lambda();
|
||||||
rb_raise(rb_eDLError, "maximum number of the argument is %d.", MAX_CBARG);
|
}
|
||||||
};
|
else{
|
||||||
|
proc = Qnil;
|
||||||
for( i = len - 1; i > 0; i-- ){
|
}
|
||||||
switch( type[i] ){
|
default:
|
||||||
case 'P':
|
break;
|
||||||
CBPUSH_P(ftype);
|
|
||||||
break;
|
|
||||||
case 'I':
|
|
||||||
CBPUSH_I(ftype);
|
|
||||||
break;
|
|
||||||
case 'L':
|
|
||||||
CBPUSH_L(ftype);
|
|
||||||
break;
|
|
||||||
case 'F':
|
|
||||||
CBPUSH_F(ftype);
|
|
||||||
break;
|
|
||||||
case 'D':
|
|
||||||
CBPUSH_D(ftype);
|
|
||||||
default:
|
|
||||||
rb_raise(rb_eDLError, "unsupported type `%c'", type[i]);
|
|
||||||
break;
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
switch( type[0] ){
|
Check_Type(type, T_STRING);
|
||||||
|
switch( STR2CSTR(type)[0] ){
|
||||||
case '0':
|
case '0':
|
||||||
CBPUSH_0(ftype);
|
rettype = 0x00;
|
||||||
break;
|
break;
|
||||||
case 'P':
|
case 'C':
|
||||||
CBPUSH_P(ftype);
|
rettype = 0x01;
|
||||||
|
break;
|
||||||
|
case 'H':
|
||||||
|
rettype = 0x02;
|
||||||
break;
|
break;
|
||||||
case 'I':
|
case 'I':
|
||||||
CBPUSH_I(ftype);
|
rettype = 0x03;
|
||||||
break;
|
break;
|
||||||
case 'L':
|
case 'L':
|
||||||
CBPUSH_L(ftype);
|
rettype = 0x04;
|
||||||
break;
|
break;
|
||||||
case 'F':
|
case 'F':
|
||||||
CBPUSH_F(ftype);
|
rettype = 0x05;
|
||||||
break;
|
break;
|
||||||
case 'D':
|
case 'D':
|
||||||
CBPUSH_D(ftype);
|
rettype = 0x06;
|
||||||
|
break;
|
||||||
|
case 'P':
|
||||||
|
rettype = 0x07;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
rb_raise(rb_eDLError, "unsupported type `%c'", type[i]);
|
rb_raise(rb_eDLTypeError, "unsupported type `%s'", STR2CSTR(rettype));
|
||||||
break;
|
|
||||||
};
|
|
||||||
|
|
||||||
return INT2NUM(ftype);
|
|
||||||
}
|
|
||||||
|
|
||||||
VALUE
|
|
||||||
rb_dl_set_callback(int argc, VALUE argv[], VALUE self)
|
|
||||||
{
|
|
||||||
VALUE types, num, proc;
|
|
||||||
VALUE key;
|
|
||||||
VALUE entry;
|
|
||||||
void *func;
|
|
||||||
|
|
||||||
char func_name[1024];
|
|
||||||
extern dln_sym();
|
|
||||||
|
|
||||||
switch( rb_scan_args(argc, argv, "21", &types, &num, &proc) ){
|
|
||||||
case 2:
|
|
||||||
proc = rb_f_lambda();
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
rb_bug("rb_dl_set_callback");
|
|
||||||
};
|
|
||||||
|
|
||||||
key = rb_dl_callback_type(&types);
|
|
||||||
entry = rb_hash_aref(DLFuncTable, key);
|
|
||||||
if( entry == Qnil ){
|
|
||||||
entry = rb_hash_new();
|
|
||||||
rb_hash_aset(DLFuncTable, key, entry);
|
|
||||||
};
|
|
||||||
|
|
||||||
func = rb_dl_func_table[NUM2INT(key)][NUM2INT(num)];
|
|
||||||
if( func ){
|
|
||||||
rb_hash_aset(entry, num, proc);
|
|
||||||
snprintf(func_name, 1023, "rb_dl_func%d_%d", NUM2INT(key), NUM2INT(num));
|
|
||||||
return rb_dlsym_new(func, func_name, RSTRING(types)->ptr);
|
|
||||||
}
|
}
|
||||||
else{
|
|
||||||
return Qnil;
|
entry = -1;
|
||||||
};
|
for( i=0; i < MAX_CALLBACK; i++ ){
|
||||||
|
if( rb_hash_aref(DLFuncTable, rb_assoc_new(INT2NUM(rettype), INT2NUM(i))) == Qnil ){
|
||||||
|
entry = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if( entry < 0 ){
|
||||||
|
rb_raise(rb_eDLError, "too many callbacks are defined.");
|
||||||
|
}
|
||||||
|
|
||||||
|
rb_hash_aset(DLFuncTable,
|
||||||
|
rb_assoc_new(INT2NUM(rettype),INT2NUM(entry)),
|
||||||
|
rb_assoc_new(type,proc));
|
||||||
|
sprintf(fname, "rb_dl_callback_func_%d_%d", rettype, entry);
|
||||||
|
return rb_dlsym_new(rb_dl_callback_table[rettype][entry], fname, STR2CSTR(type));
|
||||||
}
|
}
|
||||||
|
|
||||||
VALUE
|
static VALUE
|
||||||
rb_dl_get_callback(VALUE self, VALUE types, VALUE num)
|
rb_dl_remove_callback(VALUE mod, VALUE sym)
|
||||||
{
|
{
|
||||||
VALUE key;
|
freefunc_t f = rb_dlsym2csym(sym);
|
||||||
VALUE entry;
|
int i, j;
|
||||||
|
|
||||||
key = rb_dl_callback_type(&types);
|
for( i=0; i < CALLBACK_TYPES; i++ ){
|
||||||
entry = rb_hash_aref(DLFuncTable, key);
|
for( j=0; j < MAX_CALLBACK; j++ ){
|
||||||
if( entry == Qnil ){
|
if( rb_dl_callback_table[i][j] == f ){
|
||||||
return Qnil;
|
rb_hash_aset(DLFuncTable, rb_assoc_new(INT2NUM(i),INT2NUM(j)),Qnil);
|
||||||
};
|
break;
|
||||||
return rb_hash_aref(entry, num);
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Qnil;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -627,13 +680,12 @@ Init_dl()
|
|||||||
rb_define_const(rb_mDL, "MINOR_VERSION", INT2NUM(DL_MINOR_VERSION));
|
rb_define_const(rb_mDL, "MINOR_VERSION", INT2NUM(DL_MINOR_VERSION));
|
||||||
rb_define_const(rb_mDL, "PATCH_VERSION", INT2NUM(DL_PATCH_VERSION));
|
rb_define_const(rb_mDL, "PATCH_VERSION", INT2NUM(DL_PATCH_VERSION));
|
||||||
rb_define_const(rb_mDL, "MAX_ARG", INT2NUM(MAX_ARG));
|
rb_define_const(rb_mDL, "MAX_ARG", INT2NUM(MAX_ARG));
|
||||||
rb_define_const(rb_mDL, "MAX_CBARG", INT2NUM(MAX_CBARG));
|
|
||||||
rb_define_const(rb_mDL, "MAX_CBENT", INT2NUM(MAX_CBENT));
|
|
||||||
rb_define_const(rb_mDL, "DLSTACK", rb_tainted_str_new2(DLSTACK_METHOD));
|
rb_define_const(rb_mDL, "DLSTACK", rb_tainted_str_new2(DLSTACK_METHOD));
|
||||||
|
|
||||||
rb_define_module_function(rb_mDL, "dlopen", rb_dl_dlopen, -1);
|
rb_define_module_function(rb_mDL, "dlopen", rb_dl_dlopen, -1);
|
||||||
rb_define_module_function(rb_mDL, "set_callback", rb_dl_set_callback, -1);
|
rb_define_module_function(rb_mDL, "callback", rb_dl_callback, -1);
|
||||||
rb_define_module_function(rb_mDL, "get_callback", rb_dl_get_callback, 2);
|
rb_define_module_function(rb_mDL, "define_callback", rb_dl_callback, -1);
|
||||||
|
rb_define_module_function(rb_mDL, "remove_callback", rb_dl_remove_callback, 1);
|
||||||
rb_define_module_function(rb_mDL, "malloc", rb_dl_malloc, 1);
|
rb_define_module_function(rb_mDL, "malloc", rb_dl_malloc, 1);
|
||||||
rb_define_module_function(rb_mDL, "strdup", rb_dl_strdup, 1);
|
rb_define_module_function(rb_mDL, "strdup", rb_dl_strdup, 1);
|
||||||
rb_define_module_function(rb_mDL, "sizeof", rb_dl_sizeof, 1);
|
rb_define_module_function(rb_mDL, "sizeof", rb_dl_sizeof, 1);
|
||||||
|
@ -52,9 +52,9 @@ struct and union which are defined in "dl/struct.rb" as follows:
|
|||||||
"long tv_uses",
|
"long tv_uses",
|
||||||
]
|
]
|
||||||
end
|
end
|
||||||
val = LIBC::Timeval.alloc # allocate the memory.
|
val = LIBC::Timeval.malloc # allocate the memory.
|
||||||
|
|
||||||
The above example uses LIBC::Timeval.alloc, since we use LIBC::Timeval.new(ptr)
|
The above example uses LIBC::Timeval.malloc, since we use LIBC::Timeval.new(ptr)
|
||||||
to wrap the given PtrData object which is, for example, created by DL::malloc().
|
to wrap the given PtrData object which is, for example, created by DL::malloc().
|
||||||
DL::malloc() is a function to allocate a memory by using the C library function
|
DL::malloc() is a function to allocate a memory by using the C library function
|
||||||
malloc().
|
malloc().
|
||||||
@ -244,10 +244,10 @@ the type of each argument.
|
|||||||
p : a mutable object (void *)
|
p : a mutable object (void *)
|
||||||
0 : void function (this must be a first character of the prototype)
|
0 : void function (this must be a first character of the prototype)
|
||||||
|
|
||||||
the cbtype consists of type specifiers 0, I, L, D and P.
|
the cbtype consists of type specifiers 0, C, I, H, L, F, D, S and P.
|
||||||
for example:
|
for example:
|
||||||
|
|
||||||
DL.set_callback('IPP',0){|ptr1,ptr2|
|
DL.callback('IPP'){|ptr1,ptr2|
|
||||||
str1 = ptr1.ptr.to_s
|
str1 = ptr1.ptr.to_s
|
||||||
str2 = ptr2.ptr.to_s
|
str2 = ptr2.ptr.to_s
|
||||||
return str1 <=> str2
|
return str1 <=> str2
|
||||||
|
@ -11,10 +11,8 @@ if( ARGV.include?("--help") )
|
|||||||
--with-type-char strictly use type 'char'
|
--with-type-char strictly use type 'char'
|
||||||
--with-type-short strictly use type 'short'
|
--with-type-short strictly use type 'short'
|
||||||
--with-type-float strictly use type 'float'
|
--with-type-float strictly use type 'float'
|
||||||
--with-args=<max_arg>,<max_cbarg>,<max_cbent>
|
--with-args=<max_arg>
|
||||||
<max_arg>: maximum number of arguments of the function
|
--with-callback=<max_callback>
|
||||||
<max_cbarg>: maximum number of arguments of the callback
|
|
||||||
<max_cbent>: maximum number of callback entries
|
|
||||||
--enable-asm use the embedded assembler for passing arguments.
|
--enable-asm use the embedded assembler for passing arguments.
|
||||||
(this option is available for i386 machine now.)
|
(this option is available for i386 machine now.)
|
||||||
--enable-dlstack use a stack emulation for constructing function call.
|
--enable-dlstack use a stack emulation for constructing function call.
|
||||||
@ -58,8 +56,6 @@ $with_type_int &= DLTYPE[INT][:sym]
|
|||||||
$with_type_float &= DLTYPE[FLOAT][:sym]
|
$with_type_float &= DLTYPE[FLOAT][:sym]
|
||||||
$with_type_voidp &= DLTYPE[VOIDP][:sym]
|
$with_type_voidp &= DLTYPE[VOIDP][:sym]
|
||||||
|
|
||||||
$with_cbtype_voidp = DLTYPE[VOIDP][:cb]
|
|
||||||
|
|
||||||
$with_type_char = enable_config("type-char", $with_type_char)
|
$with_type_char = enable_config("type-char", $with_type_char)
|
||||||
$with_type_short = enable_config("type-short", $with_type_short)
|
$with_type_short = enable_config("type-short", $with_type_short)
|
||||||
$with_type_float = enable_config("type-float", $with_type_float)
|
$with_type_float = enable_config("type-float", $with_type_float)
|
||||||
@ -68,7 +64,7 @@ $with_asm = enable_config("asm", $with_asm)
|
|||||||
$with_dlstack = enable_config("dlstack", $with_dlstack)
|
$with_dlstack = enable_config("dlstack", $with_dlstack)
|
||||||
|
|
||||||
args = with_config("args")
|
args = with_config("args")
|
||||||
max_arg = max_cbarg = max_cbent = nil
|
max_arg = nil
|
||||||
if( $with_asm || $with_dlstack )
|
if( $with_asm || $with_dlstack )
|
||||||
$with_type_char = true
|
$with_type_char = true
|
||||||
$with_type_short = true
|
$with_type_short = true
|
||||||
@ -76,31 +72,20 @@ if( $with_asm || $with_dlstack )
|
|||||||
max_arg = 0
|
max_arg = 0
|
||||||
end
|
end
|
||||||
if( args )
|
if( args )
|
||||||
max_arg,max_cbarg,max_cbent = args.split(",").collect{|c| c.to_i}
|
max_arg = args.to_i
|
||||||
if( !(max_arg && max_cbarg && max_cbent) )
|
if( !max_arg )
|
||||||
print("--with-args=<max_arg>,<max_cbarg>,<max_cbent>\n")
|
print("--with-args=<max_arg>\n")
|
||||||
exit(1)
|
exit(1)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
max_arg ||= 6
|
max_arg ||= 6
|
||||||
max_cbarg ||= 3
|
|
||||||
max_cbent ||= 3
|
|
||||||
|
|
||||||
max_callback_type = types2num(DLTYPE.keys.sort[-1,1] * (max_cbarg + 1)) + 1
|
max_callback = with_config("callback","10").to_i
|
||||||
max_callback = max_cbent
|
callback_types = DLTYPE.keys.length
|
||||||
|
|
||||||
#m = [1].pack("i")
|
|
||||||
#c,cs = m.unpack("c")
|
|
||||||
#bigendian = (c == 0)
|
|
||||||
#print("bigendian ... #{bigendian ? 'true' : 'false'}\n")
|
|
||||||
|
|
||||||
|
|
||||||
$dlconfig_h = <<EOF
|
$dlconfig_h = <<EOF
|
||||||
#define MAX_ARG #{max_arg}
|
#define MAX_ARG #{max_arg}
|
||||||
#define MAX_CBARG #{max_cbarg}
|
|
||||||
#define MAX_CBENT #{max_cbent}
|
|
||||||
#define MAX_CALLBACK_TYPE #{max_callback_type}
|
|
||||||
#define MAX_CALLBACK #{max_callback}
|
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
def dlc_define(const)
|
def dlc_define(const)
|
||||||
@ -109,6 +94,8 @@ def dlc_define(const)
|
|||||||
"#endif\n"
|
"#endif\n"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
$dlconfig_h << "#define MAX_CALLBACK #{max_callback}\n"
|
||||||
|
$dlconfig_h << "#define CALLBACK_TYPES #{callback_types}\n"
|
||||||
if( $with_dlstack )
|
if( $with_dlstack )
|
||||||
$dlconfig_h << "#define USE_DLSTACK\n"
|
$dlconfig_h << "#define USE_DLSTACK\n"
|
||||||
else
|
else
|
||||||
@ -137,15 +124,6 @@ end
|
|||||||
if( $with_type_voidp )
|
if( $with_type_voidp )
|
||||||
$dlconfig_h << "#define WITH_TYPE_VOIDP\n"
|
$dlconfig_h << "#define WITH_TYPE_VOIDP\n"
|
||||||
end
|
end
|
||||||
if( $with_cbtype_voidp )
|
|
||||||
$dlconfig_h << "#define WITH_CBTYPE_VOIDP\n"
|
|
||||||
end
|
|
||||||
#if( bigendian )
|
|
||||||
# $dlconfig_h << "#define BIGENDIAN"
|
|
||||||
#else
|
|
||||||
# $dlconfig_h << "#define LITTLEENDIAN"
|
|
||||||
#end
|
|
||||||
|
|
||||||
|
|
||||||
if( have_header("dlfcn.h") )
|
if( have_header("dlfcn.h") )
|
||||||
dlc_define("HAVE_DLFCN_H")
|
dlc_define("HAVE_DLFCN_H")
|
||||||
@ -182,8 +160,8 @@ EOF
|
|||||||
|
|
||||||
File.update("dlconfig.rb", <<EOF)
|
File.update("dlconfig.rb", <<EOF)
|
||||||
MAX_ARG = #{max_arg}
|
MAX_ARG = #{max_arg}
|
||||||
MAX_CBARG = #{max_cbarg}
|
MAX_CALLBACK = #{max_callback}
|
||||||
MAX_CBENT = #{max_cbent}
|
CALLBACK_TYPES = #{callback_types}
|
||||||
DLTYPE[CHAR][:sym] = #{$with_type_char}
|
DLTYPE[CHAR][:sym] = #{$with_type_char}
|
||||||
DLTYPE[SHORT][:sym] = #{$with_type_short}
|
DLTYPE[SHORT][:sym] = #{$with_type_short}
|
||||||
DLTYPE[INT][:sym] = #{$with_type_int}
|
DLTYPE[INT][:sym] = #{$with_type_int}
|
||||||
|
@ -5,79 +5,46 @@ $:.unshift File.dirname(__FILE__)
|
|||||||
require 'type'
|
require 'type'
|
||||||
require 'dlconfig'
|
require 'dlconfig'
|
||||||
|
|
||||||
$int_eq_long = try_run(<<EOF)
|
def mkfunc(rettype, fnum, argc)
|
||||||
int main() {
|
args = (0..(argc-1)).collect{|i| "long arg#{i}"}.join(", ")
|
||||||
return sizeof(int) == sizeof(long) ? 0 : 1;
|
|
||||||
}
|
|
||||||
EOF
|
|
||||||
|
|
||||||
def func_arg(x,i)
|
subst_code = (0..(argc-1)).collect{|i|
|
||||||
ctype = DLTYPE[x][:ctype]
|
" buff[#{i.to_s}] = arg#{i.to_s};"
|
||||||
"#{ctype} arg#{i}"
|
}.join("\n")
|
||||||
end
|
|
||||||
|
|
||||||
def func_args(types)
|
ret_code =
|
||||||
t = []
|
if( DLTYPE[rettype][:c2rb] )
|
||||||
types[1..-1].each_with_index{|x,i| t.push(func_arg(x,i))}
|
" return #{DLTYPE[rettype][:rb2c][\"retval\"]};"
|
||||||
t.join(", ")
|
else
|
||||||
end
|
" /* no return value */"
|
||||||
|
end
|
||||||
|
|
||||||
def funcall_args(types)
|
code = [
|
||||||
num = types.length - 1
|
"static #{DLTYPE[rettype][:ctype]}",
|
||||||
if( num > 0 )
|
"rb_dl_callback_func_#{rettype.to_s}_#{fnum.to_s}(#{args})",
|
||||||
t = []
|
"{",
|
||||||
types[1..-1].each_with_index{|x,i| t.push(DLTYPE[x][:c2rb].call("arg#{i}"))}
|
" VALUE retval, proto, proc, obj;",
|
||||||
return num.to_s + ", " + t.join(", ")
|
" VALUE argv[#{argc.to_s}];",
|
||||||
else
|
" int argc;",
|
||||||
return num.to_s
|
" long buff[#{argc.to_s}];",
|
||||||
end
|
"",
|
||||||
end
|
subst_code,
|
||||||
|
"",
|
||||||
|
" obj = rb_hash_aref(DLFuncTable, rb_assoc_new(INT2NUM(#{rettype.to_s}),INT2NUM(#{fnum.to_s})));",
|
||||||
|
" proto = rb_ary_entry(obj, 0);",
|
||||||
|
" proc = rb_ary_entry(obj, 1);",
|
||||||
|
" rb_dl_scan_callback_args(buff, STR2CSTR(proto), &argc, &argv);",
|
||||||
|
" retval = rb_funcall2(proc, id_call, argc, argv);",
|
||||||
|
"",
|
||||||
|
ret_code,
|
||||||
|
"}",
|
||||||
|
].join("\n")
|
||||||
|
|
||||||
def output_func(types, n = 0)
|
return code
|
||||||
func_name = "rb_dl_func#{types2num(types)}_#{n}"
|
|
||||||
code =
|
|
||||||
"#{func_name}(#{func_args(types)}) /* #{types2ctypes(types).inspect} */\n" +
|
|
||||||
"{\n" +
|
|
||||||
" VALUE val, obj;\n" +
|
|
||||||
"#ifdef DEBUG\n" +
|
|
||||||
" printf(\"#{func_name}()\\n\");\n" +
|
|
||||||
"#endif\n" +
|
|
||||||
" obj = rb_hash_aref(DLFuncTable, INT2NUM(#{types2num(types)}));\n" +
|
|
||||||
" obj = rb_hash_aref(obj,INT2NUM(#{n}));\n" +
|
|
||||||
" val = rb_funcall(obj, id_call,\n" +
|
|
||||||
" #{funcall_args(types)});\n"
|
|
||||||
|
|
||||||
rtype = DLTYPE[types[0]][:ctype]
|
|
||||||
rcode = DLTYPE[types[0]][:rb2c]
|
|
||||||
if( rcode )
|
|
||||||
code += " return #{rcode.call('val')};\n"
|
|
||||||
end
|
|
||||||
|
|
||||||
code =
|
|
||||||
rtype + "\n" +
|
|
||||||
code +
|
|
||||||
"}\n\n"
|
|
||||||
if( n < MAX_CBENT - 1)
|
|
||||||
return code + output_func(types, n+1)
|
|
||||||
else
|
|
||||||
return code
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
def rec_output(types = [VOID])
|
|
||||||
print output_func(types)
|
|
||||||
if( types.length <= MAX_CBARG )
|
|
||||||
DLTYPE.keys.sort.each{|t|
|
|
||||||
if( t != VOID && DLTYPE[t][:cb] )
|
|
||||||
rec_output(types + [t])
|
|
||||||
end
|
|
||||||
}
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
DLTYPE.keys.sort.each{|t|
|
DLTYPE.keys.sort.each{|t|
|
||||||
if( DLTYPE[t][:cb] )
|
for n in 0..(MAX_CALLBACK - 1)
|
||||||
rec_output([t])
|
print(mkfunc(t, n, 15), "\n\n")
|
||||||
end
|
end
|
||||||
}
|
}
|
||||||
|
@ -5,38 +5,14 @@ $:.unshift File.dirname(__FILE__)
|
|||||||
require 'type'
|
require 'type'
|
||||||
require 'dlconfig'
|
require 'dlconfig'
|
||||||
|
|
||||||
$int_eq_long = try_run(<<EOF)
|
def mktable(rettype, fnum, argc)
|
||||||
int main() {
|
|
||||||
return sizeof(int) == sizeof(long) ? 0 : 1;
|
|
||||||
}
|
|
||||||
EOF
|
|
||||||
|
|
||||||
def output_func(types, n = 0)
|
|
||||||
code =
|
code =
|
||||||
"/* #{types2ctypes(types).inspect} */\n" +
|
"rb_dl_callback_table[#{rettype}][#{fnum}] = &rb_dl_callback_func_#{rettype.to_s}_#{fnum};"
|
||||||
"rb_dl_func_table[#{types2num(types)}][#{n}] " +
|
return code
|
||||||
"= rb_dl_func#{types2num(types)}_#{n};\n"
|
|
||||||
if( n < MAX_CBENT - 1)
|
|
||||||
return code + output_func(types, n+1)
|
|
||||||
else
|
|
||||||
return code
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
def rec_output(types = [VOID])
|
|
||||||
print output_func(types)
|
|
||||||
if( types.length <= MAX_CBARG )
|
|
||||||
DLTYPE.keys.sort.each{|t|
|
|
||||||
if( t != VOID && DLTYPE[t][:cb] )
|
|
||||||
rec_output(types + [t])
|
|
||||||
end
|
|
||||||
}
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
DLTYPE.keys.sort.each{|t|
|
DLTYPE.keys.sort.each{|t|
|
||||||
if( DLTYPE[t][:cb] )
|
for n in 0..(MAX_CALLBACK - 1)
|
||||||
rec_output([t])
|
print(mktable(t, n, 15), "\n")
|
||||||
end
|
end
|
||||||
}
|
}
|
||||||
|
@ -38,7 +38,7 @@ module LIBC
|
|||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
$cb1 = DL.set_callback('IPP', 0){|ptr1, ptr2|
|
$cb1 = DL.callback('IPP'){|ptr1, ptr2|
|
||||||
str1 = ptr1.ptr.to_s
|
str1 = ptr1.ptr.to_s
|
||||||
str2 = ptr2.ptr.to_s
|
str2 = ptr2.ptr.to_s
|
||||||
str1 <=> str2
|
str1 <=> str2
|
||||||
|
@ -38,8 +38,6 @@ print("MINOR_VERSION = #{DL::MINOR_VERSION}\n")
|
|||||||
print("\n")
|
print("\n")
|
||||||
print("DLSTACK = #{DL::DLSTACK}\n")
|
print("DLSTACK = #{DL::DLSTACK}\n")
|
||||||
print("MAX_ARG = #{DL::MAX_ARG}\n")
|
print("MAX_ARG = #{DL::MAX_ARG}\n")
|
||||||
print("MAX_CBARG = #{DL::MAX_CBARG}\n")
|
|
||||||
print("MAX_CBENT = #{DL::MAX_CBENT}\n")
|
|
||||||
print("\n")
|
print("\n")
|
||||||
print("DL::FREE = #{DL::FREE.inspect}\n")
|
print("DL::FREE = #{DL::FREE.inspect}\n")
|
||||||
print("\n")
|
print("\n")
|
||||||
@ -205,8 +203,7 @@ debug r,rs
|
|||||||
assert("callback1", :must, r == 1)
|
assert("callback1", :must, r == 1)
|
||||||
|
|
||||||
|
|
||||||
callback2 = DL.set_callback("LLP", 0){|arg1,arg2|
|
callback2 = DL.callback("LLP"){|num,ptr|
|
||||||
ptr = arg2 # DL::PtrData.new(arg2)
|
|
||||||
msg = ptr.to_s
|
msg = ptr.to_s
|
||||||
if( msg == "callback message" )
|
if( msg == "callback message" )
|
||||||
2
|
2
|
||||||
@ -218,7 +215,7 @@ debug callback2
|
|||||||
r,rs = h["test_call_func1", "IP"][callback2]
|
r,rs = h["test_call_func1", "IP"][callback2]
|
||||||
debug r,rs
|
debug r,rs
|
||||||
assert("callback2", :must, r == 2)
|
assert("callback2", :must, r == 2)
|
||||||
|
DL.remove_callback(callback2)
|
||||||
|
|
||||||
ptr = DL.malloc(DL.sizeof('CL'))
|
ptr = DL.malloc(DL.sizeof('CL'))
|
||||||
ptr.struct!("CL", :c, :l)
|
ptr.struct!("CL", :c, :l)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user