Skip to content

Commit

Permalink
* ext/dl: revert dl with libffi because it can't run on mswin now.
Browse files Browse the repository at this point in the history
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@26764 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
  • Loading branch information
nurse committed Feb 25, 2010
1 parent 9d818a2 commit 59e4e93
Show file tree
Hide file tree
Showing 19 changed files with 394 additions and 662 deletions.
4 changes: 4 additions & 0 deletions ChangeLog
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
Fri Feb 26 07:44:51 2010 NARUSE, Yui <[email protected]>

* ext/dl: revert dl with libffi because it can't run on mswin now.

Thu Feb 25 22:59:46 2010 Tanaka Akira <[email protected]>

* pack.c: consider DYNAMIC_ENDIAN. refactored.
Expand Down
15 changes: 15 additions & 0 deletions ext/dl/callback/depend
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
src: callback.c \
callback-0.c callback-1.c callback-2.c \
callback-3.c callback-4.c callback-5.c \
callback-6.c callback-7.c callback-8.c

$(OBJS): $(hdrdir)/ruby.h

callback-0.c callback-1.c callback-2.c \
callback-3.c callback-4.c callback-5.c \
callback-6.c callback-7.c callback-8.c \
: callback.c

callback.c: $(srcdir)/mkcallback.rb $(srcdir)/../dl.h
@echo "generating callback.c"
@$(RUBY) $(srcdir)/mkcallback.rb -output=callback $(srcdir)/../dl.h
14 changes: 14 additions & 0 deletions ext/dl/callback/extconf.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
require 'mkmf'

if compiled?("dl")
callbacks = (0..8).map{|i| "callback-#{i}"}.unshift("callback")
callback_srcs = callbacks.map{|basename| "#{basename}.c"}
callback_objs = callbacks.map{|basename| "#{basename}.o"}

$distcleanfiles << '$(SRCS)'
$srcs = callback_srcs
$objs = callback_objs
$INCFLAGS << " -I$(srcdir)/.."

create_makefile("dl/callback")
end
238 changes: 238 additions & 0 deletions ext/dl/callback/mkcallback.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,238 @@
#!ruby -s
$output ||= "callback"
$out = open("#{$output}.c", "w")

$dl_h = ARGV[0] || "dl.h"

# import DLSTACK_SIZE, DLSTACK_ARGS and so on
File.open($dl_h){|f|
pre = ""
f.each{|line|
line.chop!
if( line[-1] == ?\\ )
line.chop!
line.concat(" ")
pre += line
next
end
if( pre.size > 0 )
line = pre + line
pre = ""
end
case line
when /#define\s+DLSTACK_SIZE\s+\(?(\d+)\)?/
DLSTACK_SIZE = $1.to_i
when /#define\s+DLSTACK_ARGS\s+(.+)/
DLSTACK_ARGS = $1.to_i
when /#define\s+DLTYPE_([A-Z_]+)\s+\(?(\d+)\)?/
eval("#{$1} = #{$2}")
when /#define\s+MAX_DLTYPE\s+\(?(\d+)\)?/
MAX_DLTYPE = $1.to_i
when /#define\s+MAX_CALLBACK\s+\(?(\d+)\)?/
MAX_CALLBACK = $1.to_i
end
}
}

CDECL = "cdecl"
STDCALL = "stdcall"

CALLTYPES = [CDECL, STDCALL]

DLTYPE = {
VOID => {
:name => 'void',
:type => 'void',
:conv => nil,
},
CHAR => {
:name => 'char',
:type => 'char',
:conv => 'NUM2CHR(%s)'
},
SHORT => {
:name => 'short',
:type => 'short',
:conv => 'NUM2INT(%s)',
},
INT => {
:name => 'int',
:type => 'int',
:conv => 'NUM2INT(%s)',
},
LONG => {
:name => 'long',
:type => 'long',
:conv => 'NUM2LONG(%s)',
},
LONG_LONG => {
:name => 'long_long',
:type => 'LONG_LONG',
:conv => 'NUM2LL(%s)',
},
FLOAT => {
:name => 'float',
:type => 'float',
:conv => '(float)RFLOAT_VALUE(%s)',
},
DOUBLE => {
:name => 'double',
:type => 'double',
:conv => 'RFLOAT_VALUE(%s)',
},
VOIDP => {
:name => 'ptr',
:type => 'void *',
:conv => 'NUM2PTR(%s)',
},
}


def func_name(ty, argc, n, calltype)
"rb_dl_callback_#{DLTYPE[ty][:name]}_#{argc}_#{n}_#{calltype}"
end

$out << (<<EOS)
#include "ruby.h"
VALUE rb_DLCdeclCallbackAddrs, rb_DLCdeclCallbackProcs;
#ifdef FUNC_STDCALL
VALUE rb_DLStdcallCallbackAddrs, rb_DLStdcallCallbackProcs;
#endif
/*static void *cdecl_callbacks[MAX_DLTYPE][MAX_CALLBACK];*/
#ifdef FUNC_STDCALL
/*static void *stdcall_callbacks[MAX_DLTYPE][MAX_CALLBACK];*/
#endif
ID rb_dl_cb_call;
EOS

def foreach_proc_entry
for calltype in CALLTYPES
case calltype
when CDECL
proc_entry = "rb_DLCdeclCallbackProcs"
when STDCALL
proc_entry = "rb_DLStdcallCallbackProcs"
else
raise "unknown calltype: #{calltype}"
end
yield calltype, proc_entry
end
end

def gencallback(ty, calltype, proc_entry, argc, n)
<<-EOS
#{calltype == STDCALL ? "\n#ifdef FUNC_STDCALL" : ""}
static #{DLTYPE[ty][:type]}
FUNC_#{calltype.upcase}(#{func_name(ty,argc,n,calltype)})(#{(0...argc).collect{|i| "DLSTACK_TYPE stack" + i.to_s}.join(", ")})
{
VALUE ret, cb#{argc > 0 ? ", args[#{argc}]" : ""};
#{
(0...argc).collect{|i|
" args[%d] = LONG2NUM(stack%d);" % [i,i]
}.join("\n")
}
cb = rb_ary_entry(rb_ary_entry(#{proc_entry}, #{ty}), #{(n * DLSTACK_SIZE) + argc});
ret = rb_funcall2(cb, rb_dl_cb_call, #{argc}, #{argc > 0 ? 'args' : 'NULL'});
return #{DLTYPE[ty][:conv] ? DLTYPE[ty][:conv] % "ret" : ""};
}
#{calltype == STDCALL ? "#endif\n" : ""}
EOS
end

def gen_push_proc_ary(ty, aryname)
sprintf(" rb_ary_push(#{aryname}, rb_ary_new3(%d,%s));",
MAX_CALLBACK * DLSTACK_SIZE,
(0...MAX_CALLBACK).collect{
(0...DLSTACK_SIZE).collect{ "Qnil" }.join(",")
}.join(","))
end

def gen_push_addr_ary(ty, aryname, calltype)
sprintf(" rb_ary_push(#{aryname}, rb_ary_new3(%d,%s));",
MAX_CALLBACK * DLSTACK_SIZE,
(0...MAX_CALLBACK).collect{|i|
(0...DLSTACK_SIZE).collect{|argc|
"PTR2NUM(%s)" % func_name(ty,argc,i,calltype)
}.join(",")
}.join(","))
end

def gen_callback_file(ty)
filename = "#{$output}-#{ty}.c"
initname = "rb_dl_init_callbacks_#{ty}"
body = <<-EOS
#include "dl.h"
extern VALUE rb_DLCdeclCallbackAddrs, rb_DLCdeclCallbackProcs;
#ifdef FUNC_STDCALL
extern VALUE rb_DLStdcallCallbackAddrs, rb_DLStdcallCallbackProcs;
#endif
extern ID rb_dl_cb_call;
EOS
yield body
body << <<-EOS
void
#{initname}()
{
#{gen_push_proc_ary(ty, "rb_DLCdeclCallbackProcs")}
#{gen_push_addr_ary(ty, "rb_DLCdeclCallbackAddrs", CDECL)}
#ifdef FUNC_STDCALL
#{gen_push_proc_ary(ty, "rb_DLStdcallCallbackProcs")}
#{gen_push_addr_ary(ty, "rb_DLStdcallCallbackAddrs", STDCALL)}
#endif
}
EOS
[filename, initname, body]
end

callbacks = []
for ty in 0...MAX_DLTYPE
filename, initname, body = gen_callback_file(ty) {|f|
foreach_proc_entry do |calltype, proc_entry|
for argc in 0...DLSTACK_SIZE
for n in 0...MAX_CALLBACK
f << gencallback(ty, calltype, proc_entry, argc, n)
end
end
end
}
$out << "void #{initname}();\n"
callbacks << [filename, body]
end

$out << (<<EOS)
void
Init_callback(void)
{
VALUE tmp;
VALUE rb_mDL = rb_path2class("DL");
rb_dl_cb_call = rb_intern("call");
tmp = rb_DLCdeclCallbackProcs = rb_ary_new();
rb_define_const(rb_mDL, "CdeclCallbackProcs", tmp);
tmp = rb_DLCdeclCallbackAddrs = rb_ary_new();
rb_define_const(rb_mDL, "CdeclCallbackAddrs", tmp);
#ifdef FUNC_STDCALL
tmp = rb_DLStdcallCallbackProcs = rb_ary_new();
rb_define_const(rb_mDL, "StdcallCallbackProcs", tmp);
tmp = rb_DLStdcallCallbackAddrs = rb_ary_new();
rb_define_const(rb_mDL, "StdcallCallbackAddrs", tmp);
#endif
#{
(0...MAX_DLTYPE).collect{|ty|
" rb_dl_init_callbacks_#{ty}();"
}.join("\n")
}
}
EOS
$out.close

for filename, body in callbacks
open(filename, "wb") {|f| f.puts body}
end
39 changes: 15 additions & 24 deletions ext/dl/cfunc.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ rb_dl_get_last_error(VALUE self)
return rb_thread_local_aref(rb_thread_current(), id_last_error);
}

VALUE
static VALUE
rb_dl_set_last_error(VALUE self, VALUE val)
{
rb_thread_local_aset(rb_thread_current(), id_last_error, val);
Expand All @@ -33,7 +33,7 @@ rb_dl_get_win32_last_error(VALUE self)
return rb_thread_local_aref(rb_thread_current(), id_win32_last_error);
}

VALUE
static VALUE
rb_dl_set_win32_last_error(VALUE self, VALUE val)
{
rb_thread_local_aset(rb_thread_current(), id_win32_last_error, val);
Expand Down Expand Up @@ -147,12 +147,12 @@ rb_dlcfunc_initialize(int argc, VALUE argv[], VALUE self)
struct cfunc_data *data;
void *saddr;
const char *sname;

rb_scan_args(argc, argv, "13", &addr, &type, &name, &calltype);

saddr = (void*)(NUM2PTR(rb_Integer(addr)));
sname = NIL_P(name) ? NULL : StringValuePtr(name);

TypedData_Get_Struct(self, struct cfunc_data, &dlcfunc_data_type, data);
if( data->name ) xfree(data->name);
data->ptr = saddr;
Expand Down Expand Up @@ -284,11 +284,11 @@ rb_dlcfunc_inspect(VALUE self)
{
VALUE val;
char *str;
size_t str_size;
int str_size;
struct cfunc_data *cfunc;

TypedData_Get_Struct(self, struct cfunc_data, &dlcfunc_data_type, cfunc);

str_size = (cfunc->name ? strlen(cfunc->name) : 0) + 100;
str = ruby_xmalloc(str_size);
snprintf(str, str_size - 1,
Expand Down Expand Up @@ -339,31 +339,22 @@ rb_dlcfunc_call(VALUE self, VALUE ary)

memset(stack, 0, sizeof(DLSTACK_TYPE) * DLSTACK_SIZE);
Check_Type(ary, T_ARRAY);

TypedData_Get_Struct(self, struct cfunc_data, &dlcfunc_data_type, cfunc);

if( cfunc->ptr == 0 ){
rb_raise(rb_eDLError, "can't call null-function");
return Qnil;
}

if( RARRAY_LEN(ary) >= DLSTACK_SIZE ){
rb_raise(rb_eDLError, "too many arguments (stack overflow)");
}

for( i = 0; i < RARRAY_LEN(ary); i++ ){
unsigned long rb_big2ulong_pack(VALUE x);
VALUE arg = RARRAY_PTR(ary)[i];

rb_check_safe_obj(arg);
if (FIXNUM_P(arg)) {
stack[i] = FIX2LONG(arg);
}
else {
Check_Type(arg, T_BIGNUM);
stack[i] = rb_big2ulong_pack(arg);
if( i >= DLSTACK_SIZE ){
rb_raise(rb_eDLError, "too many arguments (stack overflow)");
}
rb_check_safe_obj(RARRAY_PTR(ary)[i]);
stack[i] = NUM2LONG(RARRAY_PTR(ary)[i]);
}

/* calltype == CFUNC_CDECL */
if( cfunc->calltype == CFUNC_CDECL
#ifndef FUNC_STDCALL
Expand Down
Loading

0 comments on commit 59e4e93

Please sign in to comment.