[#15625] rb_hash_initialize — Takaaki Tateishi <ttate@...>

立石です.

22 messages 2002/01/04
[#15627] Re: rb_hash_initialize — matz@... (Yukihiro Matsumoto) 2002/01/04

まつもと ゆきひろです

[#15628] Re: rb_hash_initialize — Takaaki Tateishi <ttate@...> 2002/01/04

立石です.

[#15685] undefined method `inherited' for false (NameError) — WATANABE Hirofumi <eban@...>

わたなべです。

13 messages 2002/01/15
[#15686] Re: undefined method `inherited' for false (NameError) — nobu.nakada@... 2002/01/15

なかだです。

[#15757] 文字列→整数変換 — nobu.nakada@...

なかだです。

30 messages 2002/01/25

[#15830] [ 提案 ] puts, print 等を IO から分離 — UENO Katsuhiro <unnie@...>

うえのです。

14 messages 2002/01/31

[ruby-dev:15748] Re: Win32API enhancement

From: nobu.nakada@...
Date: 2002-01-21 16:48:01 UTC
List: ruby-dev #15748
なかだです。

At Mon, 21 Jan 2002 15:52:37 +0900,
U.Nakamura <usa@osb.att.ne.jp> wrote:
> ・win32にはコールバック関数がたくさんあるが、ウィンドウプロシ
>   ージャをこうやって対応しちゃうと、他のコールバック関数に対
>   応したくなったときに収拾が取れなくなる。
>   むしろコールバック関数を扱う統一的な機構を考えた方がいいの
>   では。

こんなのとか(謎)。動くかどうかどころか、コンパイルできるかどう
かも保証の限りじゃありませんが。

# 引数の順番が逆だったかも。


# win32/callback/extconf.rb
if /i\d86-(?:cygwin|mingw|mswin)/ =~ RUBY_PLATFORM
  create_makefile("callback")
end

/*
 win32/callback/callback.c
 */
#if !defined _MSC_VER && !defined NT
#define  WIN32_LEAN_AND_MEAN
#include <windows.h>
#endif
#include <stdarg.h>

#include "ruby.h"

#ifndef EXPLICIT_RETADDR
#define EXPLICIT_RETADDR 1
#endif

static ID id_yield;

struct callback_arg {
    int nargs;
    VALUE obj;
    ID id;
    int (*defproc)();
};

static VALUE
invoke_callback(VALUE *arg)
{
    const struct callback_arg *carg = (struct callback_arg *)*arg++;
    return rb_funcall2(carg->obj, carg->id, carg->nargs, arg);
}

static int CALLBACK
win32_callback(
#if EXPLICIT_RETADDR
	       int (**retaddr)(),
#endif
	       const struct callback_arg *carg,
	       va_list vargs)
{
    int status, nargs = carg->nargs;
    VALUE *args = ALLOCA_N(VALUE, nargs+1), *p = args, ret;

    *p++ = (VALUE)carg;
    for (nargs = carg->nargs; nargs > 0; --nargs) {
	int arg = va_arg(vargs, int);
	*p++ = INT2NUM(arg);
    }
    ret = rb_protect((VALUE (*)_((VALUE)))invoke_callback, (VALUE)args, &status);
    if (status && carg->defproc) {
#if EXPLICIT_RETADDR
	*retaddr = carg->defproc;
#else
	((int (**)())&carg)[-1] = carg->defproc;
#endif
	return 0;
    }
    if (NIL_P(ret)) return 0;
    return INT2FIX(ret);
}

#ifdef _M_IX86
# if EXPLICIT_RETADDR
#   define THUNK_SIZE (sizeof(struct callback_arg) + 6 + 13)
# else
#   define THUNK_SIZE (sizeof(struct callback_arg) + 6 + 8)
# endif
#else
# error "unsupported architecture"
#endif

static VALUE
win32_callback_initialize(int argc, VALUE *argv, VALUE self)
{
    VALUE obj, nargs, defproc, code;
    ID id;
    unsigned long n;
    char *p;

    if (rb_block_given_p()) {
	obj = rb_f_lambda();
	id = rb_intern("yield");
	rb_scan_args(argc, argv, "11", &nargs, &defproc);
    }
    else {
	VALUE vid;
	rb_scan_args(argc, argv, "31", &obj, &vid, &nargs, &defproc);
	id = rb_to_id(vid);
    }

    if ((n = NUM2ULONG(nargs)) > 255) {
	rb_raise(rb_eArgError, "too many arguments %lu", n);
    }

    rb_str_resize(self, THUNK_SIZE);

    p = RSTRING(self)->ptr;

#ifdef _M_IX86
    *p++ = 0x54;		/* push	%esp */
    *p++ = 0xe8;		/* call	1f */
    *(LONG *)p = sizeof(struct callback_arg);
    p += sizeof(LONG);
    {
	struct callback_arg *carg = (struct callback_arg *)p;
	carg->nargs = nargs;
	carg->obj = obj;
	carg->id = id;
	carg->defproc = (int (*)())(NIL_P(defproc) ? 0 : defproc);
	p = (char *)++carg;
    }
    /* 1: */
# if EXPLICIT_RETADDR
    *p++ = 0x8d; *p++ = 0x44; *p++ = 0x24;*p++ = 0xf8; /* leal	-8(%esp), %eax */
    *p++ = 0x50;		/* push	%eax */
# endif
    *p++ = 0xe8;		/* call	call_callback */
    *(LONG *)p = (LONG)win32_callback - (LONG)p - sizeof(LONG);
    p += sizeof(LONG);
    *p++ = 0xc2;		/* ret nargs*4 */
    *(WORD *)p = nargs * 4;
    p += sizeof(WORD);
#endif

    rb_str_associate(self, rb_ary_new4(1, &obj));
    rb_obj_freeze(self);

    return self;
}

static VALUE
win32_callback_address(VALUE self)
{
    return INT2NUM((long)RSTRING(self)->ptr);
}

void
Init_callback(void)
{
    VALUE mWin32 = rb_define_module("Win32");
    VALUE cCallback = rb_define_class_under(mWin32, "Callback", rb_cString);
    rb_define_method(cCallback, "initialize", win32_callback_initialize, -1);
    rb_define_method(cCallback, "address", win32_callback_address, 0);
    id_yield = rb_intern("yield");
}


-- 
--- 僕の前にBugはない。
--- 僕の後ろにBugはできる。
    中田 伸悦

In This Thread