1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

remove all files to replace ruby-dl with ruby-dl2.

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@7882 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
ttate 2005-02-04 13:29:49 +00:00
parent 889ca023e3
commit 4ae9132605
30 changed files with 0 additions and 6260 deletions

View file

@ -1,46 +0,0 @@
LDSHARED_TEST = $(LDSHARED) $(LDFLAGS) test/test.o -o test/libtest.so $(LOCAL_LIBS)
libtest.so: test/libtest.so
test/libtest.so: test/test.o $(srcdir)/test/libtest.def
$(RUBY) -rftools -e 'ARGV.each do|d|File.mkpath(File.dirname(d))end' $@
$(LDSHARED_TEST:dl.def=test/libtest.def)
test/test.o: $(srcdir)/test/test.c
@$(RUBY) -rftools -e 'File.mkpath(*ARGV)' test
$(CC) $(CFLAGS) $(CPPFLAGS) -c $(srcdir)/test/test.c -o $@
test:: dl.so libtest.so force
$(RUBY) -I. -I$(srcdir)/lib $(srcdir)/test/test.rb
force:
.PHONY: force test
allclean: distclean
@rm -f $(CLEANFILES) $(DISTCLEANFILES)
$(OBJS): ./dlconfig.h
sym.o: dl.h call.func
dl.o: dl.h callback.func cbtable.func
ptr.o: dl.h
handle.o: dl.h
call.func: $(srcdir)/mkcall.rb ./dlconfig.rb
@echo "Generating call.func"
@$(RUBY) $(srcdir)/mkcall.rb > $@
callback.func: $(srcdir)/mkcallback.rb ./dlconfig.rb
@echo "Generating callback.func"
@$(RUBY) $(srcdir)/mkcallback.rb > $@
cbtable.func: $(srcdir)/mkcbtable.rb ./dlconfig.rb
@echo "Generating cbtable.func"
@$(RUBY) $(srcdir)/mkcbtable.rb > $@
debug:
$(MAKE) CPPFLAGS="$(CPPFLAGS) -DDEBUG"

View file

@ -1,721 +0,0 @@
/* -*- mode: C; c-file-style: "gnu" -*-
/*
* $Id$
*/
#include <ruby.h>
#include <rubyio.h>
#include <ctype.h>
#include "dl.h"
VALUE rb_mDL;
VALUE rb_eDLError;
VALUE rb_eDLTypeError;
static VALUE DLFuncTable;
static void *rb_dl_callback_table[CALLBACK_TYPES][MAX_CALLBACK];
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;
v = (char)(*sp);
sp++;
val = INT2NUM(v);
}
break;
case 'H':
{
short v;
v = (short)(*sp);
sp++;
val = INT2NUM(v);
}
break;
case 'I':
{
int v;
v = (int)(*sp);
sp++;
val = INT2NUM(v);
}
break;
case 'L':
{
long v;
v = (long)(*sp);
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, "scan_callback_args: unsupported type `%c'", proto[i]);
break;
}
argv[i-1] = val;
}
*argc = (i - 1);
return (*argc);
}
#include "callback.func"
static void
init_dl_func_table(){
#include "cbtable.func"
}
void *
dlmalloc(size_t size)
{
DEBUG_CODE2({
void *ptr;
printf("dlmalloc(%d)",size);
ptr = xmalloc(size);
printf(":0x%x\n",ptr);
return ptr;
},
{
return xmalloc(size);
});
}
void *
dlrealloc(void *ptr, size_t size)
{
DEBUG_CODE({
printf("dlrealloc(0x%x,%d)\n",ptr,size);
});
return xrealloc(ptr, size);
}
void
dlfree(void *ptr)
{
DEBUG_CODE({
printf("dlfree(0x%x)\n",ptr);
});
xfree(ptr);
}
char*
dlstrdup(const char *str)
{
char *newstr;
newstr = (char*)dlmalloc(strlen(str));
strcpy(newstr,str);
return newstr;
}
size_t
dlsizeof(const char *cstr)
{
size_t size;
int i, len, n, dlen;
char *d;
len = strlen(cstr);
size = 0;
for (i=0; i<len; i++) {
n = 1;
if (ISDIGIT(cstr[i+1])) {
dlen = 1;
while (ISDIGIT(cstr[i+dlen])) { dlen ++; };
dlen --;
d = ALLOCA_N(char, dlen + 1);
strncpy(d, cstr + i + 1, dlen);
d[dlen] = '\0';
n = atoi(d);
}
else{
dlen = 0;
}
switch (cstr[i]) {
case 'I':
DLALIGN(0,size,INT_ALIGN);
case 'i':
size += sizeof(int) * n;
break;
case 'L':
DLALIGN(0,size,LONG_ALIGN);
case 'l':
size += sizeof(long) * n;
break;
case 'F':
DLALIGN(0,size,FLOAT_ALIGN);
case 'f':
size += sizeof(float) * n;
break;
case 'D':
DLALIGN(0,size,DOUBLE_ALIGN);
case 'd':
size += sizeof(double) * n;
break;
case 'C':
case 'c':
size += sizeof(char) * n;
break;
case 'H':
DLALIGN(0,size,SHORT_ALIGN);
case 'h':
size += sizeof(short) * n;
break;
case 'P':
case 'S':
DLALIGN(0,size,VOIDP_ALIGN);
case 'p':
case 's':
size += sizeof(void*) * n;
break;
default:
rb_raise(rb_eDLTypeError, "unexpected type '%c'", cstr[i]);
break;
}
i += dlen;
}
return size;
}
static float *
c_farray(VALUE v, long *size)
{
int i, len;
float *ary;
VALUE e;
len = RARRAY(v)->len;
*size = sizeof(float) * len;
ary = dlmalloc(*size);
for (i=0; i < len; i++) {
e = rb_ary_entry(v, i);
switch (TYPE(e)) {
case T_FLOAT:
ary[i] = (float)(RFLOAT(e)->value);
break;
case T_NIL:
ary[i] = 0.0;
break;
default:
rb_raise(rb_eDLTypeError, "unexpected type of the element #%d", i);
break;
}
}
return ary;
}
static double *
c_darray(VALUE v, long *size)
{
int i, len;
double *ary;
VALUE e;
len = RARRAY(v)->len;
*size = sizeof(double) * len;
ary = dlmalloc(*size);
for (i=0; i < len; i++) {
e = rb_ary_entry(v, i);
switch (TYPE(e)) {
case T_FLOAT:
ary[i] = (double)(RFLOAT(e)->value);
break;
case T_NIL:
ary[i] = 0.0;
break;
default:
rb_raise(rb_eDLTypeError, "unexpected type of the element #%d", i);
break;
}
}
return ary;
}
static long *
c_larray(VALUE v, long *size)
{
int i, len;
long *ary;
VALUE e;
len = RARRAY(v)->len;
*size = sizeof(long) * len;
ary = dlmalloc(*size);
for (i=0; i < len; i++) {
e = rb_ary_entry(v, i);
switch (TYPE(e)) {
case T_FIXNUM:
case T_BIGNUM:
ary[i] = (long)(NUM2INT(e));
break;
case T_NIL:
ary[i] = 0;
break;
default:
rb_raise(rb_eDLTypeError, "unexpected type of the element #%d", i);
break;
}
}
return ary;
}
static int *
c_iarray(VALUE v, long *size)
{
int i, len;
int *ary;
VALUE e;
len = RARRAY(v)->len;
*size = sizeof(int) * len;
ary = dlmalloc(*size);
for (i=0; i < len; i++) {
e = rb_ary_entry(v, i);
switch (TYPE(e)) {
case T_FIXNUM:
case T_BIGNUM:
ary[i] = (int)(NUM2INT(e));
break;
case T_NIL:
ary[i] = 0;
break;
default:
rb_raise(rb_eDLTypeError, "unexpected type of the element #%d", i);
break;
}
}
return ary;
}
static short *
c_harray(VALUE v, long *size)
{
int i, len;
short *ary;
VALUE e;
len = RARRAY(v)->len;
*size = sizeof(short) * len;
ary = dlmalloc(*size);
for (i=0; i < len; i++) {
e = rb_ary_entry(v, i);
switch (TYPE(e)) {
case T_FIXNUM:
case T_BIGNUM:
ary[i] = (short)(NUM2INT(e));
break;
case T_NIL:
ary[i] = 0;
break;
default:
rb_raise(rb_eDLTypeError, "unexpected type of the element #%d", i);
break;
}
}
return ary;
}
static char *
c_carray(VALUE v, long *size)
{
int i, len;
char *ary;
VALUE e;
len = RARRAY(v)->len;
*size = sizeof(char) * len;
ary = dlmalloc(*size);
for (i=0; i < len; i++) {
e = rb_ary_entry(v, i);
switch (TYPE(e)) {
case T_FIXNUM:
case T_BIGNUM:
ary[i] = (char)(NUM2INT(e));
break;
case T_NIL:
ary[i] = 0;
break;
default:
rb_raise(rb_eDLTypeError, "unexpected type of the element #%d", i);
break;
}
}
return ary;
}
static void *
c_parray(VALUE v, long *size)
{
int i, len;
void **ary;
VALUE e, tmp;
len = RARRAY(v)->len;
*size = sizeof(void*) * len;
ary = dlmalloc(*size);
for (i=0; i < len; i++) {
e = rb_ary_entry(v, i);
switch (TYPE(e)) {
default:
tmp = rb_check_string_type(e);
if (NIL_P(tmp)) {
rb_raise(rb_eDLTypeError, "unexpected type of the element #%d", i);
}
e = tmp;
/* fall through */
case T_STRING:
rb_check_safe_str(e);
{
char *str, *src;
src = RSTRING(e)->ptr;
str = dlstrdup(src);
ary[i] = (void*)str;
}
break;
case T_NIL:
ary[i] = NULL;
break;
case T_DATA:
if (rb_obj_is_kind_of(e, rb_cDLPtrData)) {
struct ptr_data *pdata;
Data_Get_Struct(e, struct ptr_data, pdata);
ary[i] = (void*)(pdata->ptr);
}
else{
rb_raise(rb_eDLTypeError, "unexpected type of the element #%d", i);
}
break;
}
}
return ary;
}
void *
rb_ary2cary(char t, VALUE v, long *size)
{
int len;
VALUE val0;
val0 = rb_check_array_type(v);
if(NIL_P(TYPE(val0))) {
rb_raise(rb_eDLTypeError, "an array is expected.");
}
v = val0;
len = RARRAY(v)->len;
if (len == 0) {
return NULL;
}
if (!size) {
size = ALLOCA_N(long,1);
}
val0 = rb_ary_entry(v,0);
switch (TYPE(val0)) {
case T_FIXNUM:
case T_BIGNUM:
switch (t) {
case 'C': case 'c':
return (void*)c_carray(v,size);
case 'H': case 'h':
return (void*)c_harray(v,size);
case 'I': case 'i':
return (void*)c_iarray(v,size);
case 'L': case 'l': case 0:
return (void*)c_larray(v,size);
default:
rb_raise(rb_eDLTypeError, "type mismatch");
}
case T_STRING:
return (void*)c_parray(v,size);
case T_FLOAT:
switch (t) {
case 'F': case 'f':
return (void*)c_farray(v,size);
case 'D': case 'd': case 0:
return (void*)c_darray(v,size);
}
rb_raise(rb_eDLTypeError, "type mismatch");
case T_DATA:
if (rb_obj_is_kind_of(val0, rb_cDLPtrData)) {
return (void*)c_parray(v,size);
}
rb_raise(rb_eDLTypeError, "type mismatch");
case T_NIL:
return (void*)c_parray(v, size);
default:
rb_raise(rb_eDLTypeError, "unsupported type");
}
}
VALUE
rb_str_to_ptr(VALUE self)
{
char *ptr;
int len;
len = RSTRING(self)->len;
ptr = (char*)dlmalloc(len + 1);
memcpy(ptr, RSTRING(self)->ptr, len);
ptr[len] = '\0';
return rb_dlptr_new((void*)ptr,len,dlfree);
}
VALUE
rb_ary_to_ptr(int argc, VALUE argv[], VALUE self)
{
void *ptr;
VALUE t;
long size;
switch (rb_scan_args(argc, argv, "01", &t)) {
case 1:
ptr = rb_ary2cary(StringValuePtr(t)[0], self, &size);
break;
case 0:
ptr = rb_ary2cary(0, self, &size);
break;
}
return ptr ? rb_dlptr_new(ptr, size, dlfree) : Qnil;
}
VALUE
rb_io_to_ptr(VALUE self)
{
OpenFile *fptr;
FILE *fp;
GetOpenFile(self, fptr);
fp = rb_io_stdio_file(fptr);
return fp ? rb_dlptr_new(fp, sizeof(FILE), 0) : Qnil;
}
VALUE
rb_dl_dlopen(int argc, VALUE argv[], VALUE self)
{
rb_secure(4);
return rb_class_new_instance(argc, argv, rb_cDLHandle);
}
VALUE
rb_dl_malloc(VALUE self, VALUE size)
{
rb_secure(4);
return rb_dlptr_malloc(DLNUM2LONG(size), dlfree);
}
VALUE
rb_dl_strdup(VALUE self, VALUE str)
{
void *ptr;
long len;
SafeStringValue(str);
len = RSTRING(str)->len;
ptr = memcpy(dlmalloc(len + 1), RSTRING(str)->ptr, len + 1);
((char *)ptr)[len] = '\0';
return rb_dlptr_new(ptr, len, dlfree);
}
static VALUE
rb_dl_sizeof(VALUE self, VALUE str)
{
return INT2NUM(dlsizeof(StringValuePtr(str)));
}
static VALUE
rb_dl_callback(int argc, VALUE argv[], VALUE self)
{
VALUE type, proc;
int rettype, entry, i;
char fname[127];
rb_secure(4);
proc = Qnil;
switch (rb_scan_args(argc, argv, "11", &type, &proc)) {
case 1:
if (rb_block_given_p()) {
proc = rb_block_proc();
}
else{
proc = Qnil;
}
default:
break;
}
StringValue(type);
switch (RSTRING(type)->ptr[0]) {
case '0':
rettype = 0x00;
break;
case 'C':
rettype = 0x01;
break;
case 'H':
rettype = 0x02;
break;
case 'I':
rettype = 0x03;
break;
case 'L':
rettype = 0x04;
break;
case 'F':
rettype = 0x05;
break;
case 'D':
rettype = 0x06;
break;
case 'P':
rettype = 0x07;
break;
default:
rb_raise(rb_eDLTypeError, "unsupported type `%c'", RSTRING(type)->ptr[0]);
}
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((void (*)())rb_dl_callback_table[rettype][entry],
fname, RSTRING(type)->ptr);
}
static VALUE
rb_dl_remove_callback(VALUE mod, VALUE sym)
{
freefunc_t f;
int i, j;
rb_secure(4);
f = rb_dlsym2csym(sym);
for (i=0; i < CALLBACK_TYPES; i++) {
for (j=0; j < MAX_CALLBACK; j++) {
if (rb_dl_callback_table[i][j] == f) {
rb_hash_aset(DLFuncTable, rb_assoc_new(INT2NUM(i),INT2NUM(j)),Qnil);
break;
}
}
}
return Qnil;
}
void
Init_dl()
{
void Init_dlptr();
void Init_dlsym();
void Init_dlhandle();
id_call = rb_intern("call");
rb_mDL = rb_define_module("DL");
rb_eDLError = rb_define_class_under(rb_mDL, "DLError", rb_eStandardError);
rb_eDLTypeError = rb_define_class_under(rb_mDL, "DLTypeError", rb_eDLError);
DLFuncTable = rb_hash_new();
init_dl_func_table();
rb_define_const(rb_mDL, "FuncTable", DLFuncTable);
rb_define_const(rb_mDL, "RTLD_GLOBAL", INT2NUM(RTLD_GLOBAL));
rb_define_const(rb_mDL, "RTLD_LAZY", INT2NUM(RTLD_LAZY));
rb_define_const(rb_mDL, "RTLD_NOW", INT2NUM(RTLD_NOW));
rb_define_const(rb_mDL, "ALIGN_INT", INT2NUM(ALIGN_INT));
rb_define_const(rb_mDL, "ALIGN_LONG", INT2NUM(ALIGN_LONG));
rb_define_const(rb_mDL, "ALIGN_FLOAT", INT2NUM(ALIGN_FLOAT));
rb_define_const(rb_mDL, "ALIGN_SHORT", INT2NUM(ALIGN_SHORT));
rb_define_const(rb_mDL, "ALIGN_DOUBLE",INT2NUM(ALIGN_DOUBLE));
rb_define_const(rb_mDL, "ALIGN_VOIDP", INT2NUM(ALIGN_VOIDP));
rb_define_const(rb_mDL, "MAX_ARG", INT2NUM(MAX_ARG));
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, "callback", rb_dl_callback, -1);
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, "strdup", rb_dl_strdup, 1);
rb_define_module_function(rb_mDL, "sizeof", rb_dl_sizeof, 1);
Init_dlptr();
Init_dlsym();
Init_dlhandle();
rb_define_const(rb_mDL, "FREE", rb_dlsym_new(dlfree, "free", "0P"));
rb_define_method(rb_cString, "to_ptr", rb_str_to_ptr, 0);
rb_define_method(rb_cArray, "to_ptr", rb_ary_to_ptr, -1);
rb_define_method(rb_cIO, "to_ptr", rb_io_to_ptr, 0);
}

View file

@ -1,59 +0,0 @@
EXPORTS
Init_dl
dlfree
dlmalloc
dlrealloc
dlstrdup
rb_ary_to_ptr
rb_dl_dlopen
rb_dl_malloc
rb_dl_strdup
rb_eDLError
rb_eDLTypeError
rb_io_to_ptr
rb_mDL
rb_str_to_ptr
Init_dlhandle
rb_cDLHandle
rb_dlhandle_close
rb_dlhandle_disable_close
rb_dlhandle_enable_close
rb_dlhandle_sym
Init_dlptr
rb_cDLPtrData
rb_dlmem_each
rb_dlptr2cptr
rb_dlptr_malloc
rb_dlptr_aref
rb_dlptr_aset
rb_dlptr_cmp
rb_dlptr_define_data_type
rb_dlptr_define_struct
rb_dlptr_define_union
rb_dlptr_eql
rb_dlptr_free_get
rb_dlptr_free_set
rb_dlptr_get_data_type
rb_dlptr_inspect
rb_dlptr_minus
rb_dlptr_new
rb_dlptr_new2
rb_dlptr_null_p
rb_dlptr_plus
rb_dlptr_ptr
rb_dlptr_ref
rb_dlptr_to_array
rb_dlptr_to_i
rb_dlptr_to_s
rb_dlptr_to_str
rb_mDLMemorySpace
Init_dlsym
rb_cDLSymbol
rb_dlsym2csym
rb_dlsym_call
rb_dlsym_cproto
rb_dlsym_inspect
rb_dlsym_name
rb_dlsym_new
rb_dlsym_proto
rb_dlsym_to_ptr

View file

@ -1,313 +0,0 @@
/* -*- mode: C; c-file-style: "gnu" -*-
* $Id$
*/
#ifndef RUBY_DL_H
#define RUBY_DL_H
#include <ruby.h>
#include <dlconfig.h>
#if defined(HAVE_DLFCN_H)
# include <dlfcn.h>
# /* some stranger systems may not define all of these */
#ifndef RTLD_LAZY
#define RTLD_LAZY 0
#endif
#ifndef RTLD_GLOBAL
#define RTLD_GLOBAL 0
#endif
#ifndef RTLD_NOW
#define RTLD_NOW 0
#endif
#else
# if defined(HAVE_WINDOWS_H)
# include <windows.h>
# define dlclose(ptr) FreeLibrary((HINSTANCE)ptr)
# define dlopen(name,flag) ((void*)LoadLibrary(name))
# define dlerror() "unknown error"
# define dlsym(handle,name) ((void*)GetProcAddress(handle,name))
# define RTLD_LAZY -1
# define RTLD_NOW -1
# define RTLD_GLOBAL -1
# endif
#endif
#if !defined(StringValue)
# define StringValue(v) if(TYPE(v) != T_STRING) v = rb_str_to_str(v)
#endif
#if !defined(StringValuePtr)
# define StringValuePtr(v) RSTRING((TYPE(v) == T_STRING) ? (v) : rb_str_to_str(v))->ptr
#endif
#ifdef DEBUG
#define DEBUG_CODE(b) {printf("DEBUG:%d\n",__LINE__);b;}
#define DEBUG_CODE2(b1,b2) {printf("DEBUG:%d\n",__LINE__);b1;}
#else
#define DEBUG_CODE(b)
#define DEBUG_CODE2(b1,b2) b2
#endif
#define VOID_DLTYPE 0x00
#define CHAR_DLTYPE 0x01
#define SHORT_DLTYPE 0x02
#define INT_DLTYPE 0x03
#define LONG_DLTYPE 0x04
#define FLOAT_DLTYPE 0x05
#define DOUBLE_DLTYPE 0x06
#define VOIDP_DLTYPE 0x07
#define ARG_TYPE(x,i) (((x) & (0x07 << ((i)*3))) >> ((i)*3))
#define PUSH_ARG(x,t) do{x <<= 3; x |= t;}while(0)
#define PUSH_0(x) PUSH_ARG(x,VOID_DLTYPE)
#if SIZEOF_INT == SIZEOF_LONG
# define PUSH_I(x) PUSH_ARG(x,LONG_DLTYPE)
# define ANY2I(x) x.l
# define DLINT(x) (long)x
#else
# define PUSH_I(x) PUSH_ARG(x,INT_DLTYPE)
# define ANY2I(x) x.i
# define DLINT(x) (int)x
#endif
#define PUSH_L(x) PUSH_ARG(x,LONG_DLTYPE)
#define ANY2L(x) x.l
#define DLLONG(x) (long)x
#if defined(WITH_TYPE_FLOAT)
# if SIZEOF_FLOAT == SIZEOF_DOUBLE
# define PUSH_F(x) PUSH_ARG(x,DOUBLE_DLTYPE)
# define ANY2F(x) (x.d)
# define DLFLOAT(x) ((double)x)
# else
# define PUSH_F(x) PUSH_ARG(x,FLOAT_DLTYPE)
# define ANY2F(x) (x.f)
# define DLFLOAT(x) ((float)x)
# endif
#else
# define PUSH_F(x) PUSH_ARG(x,DOUBLE_DLTYPE)
# define ANY2F(x) (x.d)
# define DLFLOAT(x) ((double)x)
#endif
#define PUSH_D(x) PUSH_ARG(x,DOUBLE_DLTYPE)
#define ANY2D(x) (x.d)
#define DLDOUBLE(x) ((double)x)
#if SIZEOF_INT == SIZEOF_VOIDP && SIZEOF_INT != SIZEOF_LONG
# define PUSH_P(x) PUSH_ARG(x,INT_DLTYPE)
# define ANY2P(x) (x.i)
# define DLVOIDP(x) ((int)x)
#elif SIZEOF_LONG == SIZEOF_VOIDP
# define PUSH_P(x) PUSH_ARG(x,LONG_DLTYPE)
# define ANY2P(x) (x.l)
# define DLVOIDP(x) ((long)x)
#else
# define PUSH_P(x) PUSH_ARG(x,VOIDP_DLTYPE)
# define ANY2P(x) (x.p)
# define DLVOIDP(x) ((void*)p)
#endif
#if defined(WITH_TYPE_CHAR)
# define PUSH_C(x) PUSH_ARG(x,CHAR_DLTYPE)
# define ANY2C(x) (x.c)
# define DLCHAR(x) ((char)x)
#else
# define PUSH_C(x) PUSH_I(x)
# define ANY2C(x) ANY2I(x)
# define DLCHAR(x) DLINT(x)
#endif
#if defined(WITH_TYPE_SHORT)
# define PUSH_H(x) PUSH_ARG(x,SHORT_DLTYPE)
# define ANY2H(x) (x.h)
# define DLSHORT(x) ((short)x)
#else
# define PUSH_H(x) PUSH_I(x)
# define ANY2H(x) ANY2I(x)
# define DLSHORT(x) DLINT(x)
#endif
#define PUSH_S(x) PUSH_P(x)
#define ANY2S(x) ANY2P(x)
#define DLSTR(x) DLVOIDP(x)
#define CBPUSH_0(x) PUSH_0(x)
#define CBPUSH_C(x) PUSH_C(x)
#define CBPUSH_H(x) PUSH_H(x)
#define CBPUSH_I(x) PUSH_I(x)
#define CBPUSH_L(x) PUSH_L(x)
#define CBPUSH_F(x) PUSH_F(x)
#define CBPUSH_D(x) PUSH_D(x)
#if defined(WITH_CBTYPE_VOIDP)
# define CBPUSH_P(x) PUSH_ARG(x,VOIDP_DLTYPE)
#else
# define CBPUSH_P(x) PUSH_P(x)
#endif
#if defined(USE_INLINE_ASM)
# if defined(__i386__) && defined(__GNUC__)
# define DLSTACK
# define DLSTACK_METHOD "asm"
# define DLSTACK_REVERSE
# define DLSTACK_PROTO
# define DLSTACK_ARGS
# define DLSTACK_START(sym)
# define DLSTACK_END(sym)
# define DLSTACK_PUSH_C(x) asm volatile ("pushl %0" :: "g" (x));
# define DLSTACK_PUSH_H(x) asm volatile ("pushl %0" :: "g" (x));
# define DLSTACK_PUSH_I(x) asm volatile ("pushl %0" :: "g" (x));
# define DLSTACK_PUSH_L(x) asm volatile ("pushl %0" :: "g" (x));
# define DLSTACK_PUSH_P(x) asm volatile ("pushl %0" :: "g" (x));
# define DLSTACK_PUSH_F(x) asm volatile ("flds %0"::"g"(x));\
asm volatile ("subl $4,%esp");\
asm volatile ("fstps (%esp)");
# define DLSTACK_PUSH_D(x) asm volatile ("fldl %0"::"g"(x));\
asm volatile ("subl $8,%esp");\
asm volatile ("fstpl (%esp)")
# else
# error --with-asm is not supported on this machine
# endif
#elif defined(USE_DLSTACK)
# define DLSTACK
# define DLSTACK_GUARD
# define DLSTACK_METHOD "dl"
# define DLSTACK_PROTO long,long,long,long,long,\
long,long,long,long,long,\
long,long,long,long,long
# define DLSTACK_ARGS stack[0],stack[1],stack[2],stack[3],stack[4],\
stack[5],stack[6],stack[7],stack[8],stack[9],\
stack[10],stack[11],stack[12],stack[13],stack[14]
# define DLSTACK_SIZE (sizeof(long)*15)
# define DLSTACK_START(sym)
# define DLSTACK_END(sym)
# define DLSTACK_PUSH_C(x) {long v=(long)x; memcpy(sp,&v,sizeof(long)); sp++;}
# define DLSTACK_PUSH_H(x) {long v=(long)x; memcpy(sp,&v,sizeof(long)); sp++;}
# define DLSTACK_PUSH_I(x) {long v=(long)x; memcpy(sp,&v,sizeof(long)); sp++;}
# define DLSTACK_PUSH_L(x) memcpy(sp,&x,sizeof(long)); sp++;
# define DLSTACK_PUSH_P(x) memcpy(sp,&x,sizeof(void*)); sp++;
# define DLSTACK_PUSH_F(x) memcpy(sp,&x,sizeof(float)); sp+=sizeof(float)/sizeof(long);
# define DLSTACK_PUSH_D(x) memcpy(sp,&x,sizeof(double)); sp+=sizeof(double)/sizeof(long);
#else
# define DLSTACK_METHOD "none"
#endif
extern VALUE rb_mDL;
extern VALUE rb_mDLMemorySpace;
extern VALUE rb_cDLHandle;
extern VALUE rb_cDLSymbol;
extern VALUE rb_cDLPtrData;
extern VALUE rb_cDLStructData;
extern VALUE rb_eDLError;
extern VALUE rb_eDLTypeError;
#if defined(LONG2NUM) && (SIZEOF_LONG == SIZEOF_VOIDP)
# define DLLONG2NUM(x) LONG2NUM((long)x)
# define DLNUM2LONG(x) (long)(NUM2LONG(x))
#else
# define DLLONG2NUM(x) INT2NUM((long)x)
# define DLNUM2LONG(x) (long)(NUM2INT(x))
#endif
typedef struct { char c; void *x; } s_voidp;
typedef struct { char c; short x; } s_short;
typedef struct { char c; int x; } s_int;
typedef struct { char c; long x; } s_long;
typedef struct { char c; float x; } s_float;
typedef struct { char c; double x; } s_double;
#define ALIGN_VOIDP (sizeof(s_voidp) - sizeof(void *))
#define ALIGN_SHORT (sizeof(s_short) - sizeof(short))
#define ALIGN_INT (sizeof(s_int) - sizeof(int))
#define ALIGN_LONG (sizeof(s_long) - sizeof(long))
#define ALIGN_FLOAT (sizeof(s_float) - sizeof(float))
#define ALIGN_DOUBLE (sizeof(s_double) - sizeof(double))
/* for compatibility */
#define VOIDP_ALIGN ALIGN_VOIDP
#define SHORT_ALIGN ALIGN_SHORT
#define INT_ALIGN ALIGN_INT
#define LONG_ALIGN ALIGN_LONG
#define FLOAT_ALIGN ALIGN_FLOAT
#define DOUBLE_ALIGN ALIGN_DOUBLE
#define DLALIGN(ptr,offset,align) {\
while( (((unsigned long)((char *)ptr + offset)) % align) != 0 ) offset++;\
}
typedef void (*freefunc_t)(void *);
#define DLFREEFUNC(func) ((freefunc_t)(func))
typedef union {
void* p;
char c;
short h;
int i;
long l;
float f;
double d;
char *s;
} ANY_TYPE;
struct dl_handle {
void *ptr;
int open;
int enable_close;
};
struct sym_data {
void *func;
char *name;
char *type;
int len;
};
enum DLPTR_CTYPE {
DLPTR_CTYPE_UNKNOWN,
DLPTR_CTYPE_STRUCT,
DLPTR_CTYPE_UNION
};
struct ptr_data {
void *ptr; /* a pointer to the data */
freefunc_t free; /* free() */
char *stype; /* array of type specifiers */
int *ssize; /* size[i] = sizeof(type[i]) > 0 */
int slen; /* the number of type specifiers */
ID *ids;
int ids_num;
int ctype; /* DLPTR_CTYPE_UNKNOWN, DLPTR_CTYPE_STRUCT, DLPTR_CTYPE_UNION */
long size;
};
#define RDLPTR(obj) ((struct ptr_data *)(DATA_PTR(obj)))
#define RDLSYM(obj) ((struct sym_data *)(DATA_PTR(obj)))
void dlfree(void*);
void *dlmalloc(size_t);
void *dlrealloc(void*,size_t);
char *dlstrdup(const char *);
size_t dlsizeof(const char *);
void *rb_ary2cary(char t, VALUE ary, long *size);
/*
void rb_dlmem_delete(void *ptr);
void rb_dlmem_aset(void *ptr, VALUE obj);
VALUE rb_dlmem_aref(void *ptr);
*/
void dlptr_free(struct ptr_data *data);
void dlptr_init(VALUE val);
VALUE rb_dlptr_new(void *ptr, long size, freefunc_t func);
VALUE rb_dlptr_new2(VALUE klass, void *ptr, long size, freefunc_t func);
VALUE rb_dlptr_malloc(long size, freefunc_t func);
void *rb_dlptr2cptr(VALUE val);
VALUE rb_dlsym_new(void (*func)(), const char *name, const char *type);
freefunc_t rb_dlsym2csym(VALUE val);
#endif /* RUBY_DL_H */

View file

@ -1,266 +0,0 @@
=begin
= Ruby/DL
Ruby/DL provides an interface to the dynamic linker such as dlopen() on UNIX
and LoadLibrary() on Windows.
= Building and Installing
$ ruby extconf.rb # to create the Makefile
$ make # to build the library 'dl.so'
$ make libtest.so # to build the C library 'libtest.so' for the test script
$ make test # to run the test script
$ make install # to install the library
$ make clean # to remove the created files without Makefile
$ make distclean # to remove the all created files
= Using Ruby/DL
We should usually use DL::Importable module provided by "dl/import.rb".
It has high-level functions to access library functions. We use
DL::Importable module to extend a module as follows:
require "dl/import"
module LIBC
extend DL::Importable
end
Now we can use methods dlload and extern in this module. We load the
libraries using dlload, and define wrapper methods to library functions
using extern respectively as follows:
module LIBC
extend DL::Importable
dlload "libc.so.6","libm.so.6"
extern "int strlen(char*)"
end
# Note that we should not include the module LIBC from some reason.
We can call the library function strlen() using LIBC.strlen. If the first
character of given function name is an uppercase, the first character of the
defined method name becomes lowercase.
We can also construct memory images of structures and unions using functions
struct and union which are defined in "dl/struct.rb" as follows:
require "dl/import"
require "dl/struct"
module LIBC
extend DL::Importable
Timeval = struct [ # define timeval structure.
"long tv_sec",
"long tv_uses",
]
end
val = LIBC::Timeval.malloc # allocate memory.
Notice that the above example takes LIBC::Timeval.malloc to allocate memory,
rather than LIBC::Timeval.new. It is because DL::Timeval.new is for wrapping
an object, PtrData, which has already been created.
We can define a callback using the module function "callback" as follows:
module Foo
extend DL::Importable
def my_comp(str1,str2)
str1 <=> str2
end
COMPARE = callback "int my_comp(char*,char*)"
end
where Foo::COMPARE is a Symbol object which invokes the method "my_comp".
DL::Importable module is very useful. However, we sometimes encounter a case
that we must directly use low-level functions such as dlsym(). In such case,
we would use DL module functions. They are described in next section.
= DL module
Module DL consists of three classes, a few module functions and constants.
The class Symbol represents the symbol we can call. The class PtrData
indicates a memory block such as a pointer in C. An object instantiated from
the class Handle keeps a handle to opened library.
== Constants
* VERSION
* MAJOR_VERSION
* MINOR_VERSION
* PATCH_VERSION
* RTLD_GLOBAL
* RTLD_LAZY
* RTLD_NOW
* MAX_ARG
* MAX_CBARG
* MAX_CBENT
== Functions
* handle = dlopen(lib){|handle| ... }
* is quite equal to `Handle.new(lib)'
* sym = set_callback(cbtype, entry){|args| ... }
* sym = set_callback(cbtype, entry, proc)
* makes entry-th pre-defined function to call the proc or given block. the
entry-th pre-defined function is specified by cbtype and entry. cbtype is a
prototype of the callback. see also the section `Type specifiers' about
cbtype.
* sym = get_callback(cbtype, entry)
* returns the Proc object which is given by the above function
`set_callback'.
* ptr = malloc(size, [free = nil])
* allocates the size bytes, and returns the pointer as a PtrData object ptr.
* ptr = strdup(str)
* returns a PtrData object ptr which represents the pointer to a new string
which is a duplicate of the string str.
* size = sizeof(type)
* returns the size of type. `sizeof("C") + sizeof("L")' is not equal to
`sizeof("CL")'. the latter is assumed to returns the enough size of the
structure `struct foo { char c; long l; }', but the size may not equal to
`sizeof(foo)' of C.
== Handle class
* handle = Handle.new(lib){|handle| ... }
* opens a library lib and returns a Handle object handle. if a block is
given, the handle is automatically closed as the block ends.
* Handle#close
* closes the handle opened by the above Handle.new(lib).
* sym = Handle#sym(func, prototype = "0"),
sym = Handle#[func, prototype = nil]
* obtains the pointer to a function called func and returns a Symbol object
or a DataPtr object. prototype is a string which consists of type
specifiers, it indicates the function's prototype. see also the section
`Type specifiers'.
== Symbol class
* sym = Symbol.new(addr, type = nil, name = nil)
* creates the Symbol object sym with the type type if type is not nil. addr
is the address where the function is allocated. If type is nil, it returns
a DataPtr object.
* Symbol::char2type(char)
* takes a character char that represents a type and returns the type
specifier of the C language.
* str = Symbol#proto()
* returns the function prototype.
* str = Symbol#name()
* Returns the function name.
* str = Symbol#cproto(),
str = Symbol#to_s()
* returns the prototype of the C language.
* str = Symbol#inspect()
* returns the inspectable string.
* r,rs = Symbol#call(arg1,arg2,...,argN),
r,rs = Symbol#[](arg1,arg2,...,argN)
* calls the function with parameters arg1, arg2, ..., argN. and the result
consists of the return value r and parameters rs. rs is an array.
* ptr = Symbol#to_ptr
* returns the corresponding PtrData object ptr.
== PtrData class
* ptr = PtrData.new(addr, [size = 0, free = nil])
* returns the PtrData object representing the pointer which indicates the
address addr. GC frees the memory using the free function.
* PtrData#free=(sym)
* If you specify a symbol object sym, GC frees the memory using the function
represented by sym.
* sym = PtrData#free
* returns a symbol object sym which is used when GC frees the memory. it
usually configured by `PtrData#free=' or `PtrData.new'.
* size = PtrData#size, PtrData#size=(size)
* gets and sets allocated size of the memory.
* ary = PtrData#to_a(type, [size])
* returns an array of the type which specified with type. type must be one of
'S','P','I','L','D' and 'F'.
* str = PtrData#to_s([len])
* returns a string which length is len. if len is omitted, the end of the
string is '\0'.
* ptr = PtrData#ptr,+@
* returns the pointed value as a PtrData object ptr.
* ptr = PtrData#ref,-@
* returns the reference as a PtrData object ptr.
* ptr = PtrData#+
* returns the PtrData object
* ptr = PtrData#-
* returns the PtrData object
* PtrData#struct!(type, *members)
* defines the data type to get access to a structure member with a symbol.
(see also PtrData#[])
* PtrData#union!(type, *members)
* defines the data type to get access to a union member with a symbol. (see
also PtrData#[])
* val = PtrData#[key], PtrData#[key, num = 0]
* if the key is a string or symbol, this method returns the value of the
structure/union member which has the type defined by PtrData#
{struct!,union!}. if the key is a integer value and this object represents
the pointer ptr, it returns the value of `(ptr + key).to_s(num)'
* PtrData#[key,num]=val, PtrData#[key]=val
* if the key is a string or symbol, this method substitute the value of the
structure/union member with val. if the key is a integer value and val is a
string, this method copies num bytes of val to the memory area ptr using
memcpy(3).
== Type specifiers
the prototype consists of the following type specifiers, first element of
prototype represents the type of return value, and remaining elements represent
the type of each argument.
C : char
c : char *
H : short
h : short *
I : int
i : int *
L : long
l : long *
F : float
f : float *
D : double
d : double *
S : const char *
s : char *
A : const type[]
a : type[] (allocates new memory space)
P : void * (same as 'p')
p : void * (same as 'P')
0 : void function (this must be a first character of the prototype)
the cbtype consists of type specifiers 0, C, I, H, L, F, D, S and P.
for example:
DL.callback('IPP'){|ptr1,ptr2|
str1 = ptr1.ptr.to_s
str2 = ptr2.ptr.to_s
str1 <=> str2
}
=end

View file

@ -1,193 +0,0 @@
require 'mkmf'
begin # for the exception SystemExit
$:.unshift File.dirname(__FILE__)
require 'type'
if( ARGV.include?("--help") )
print <<EOF
--help print this messages
--with-type-char strictly use type 'char'
--with-type-short strictly use type 'short'
--with-type-float strictly use type 'float'
--with-args=<max_arg>
--with-callback=<max_callback>
--enable-asm use the embedded assembler for passing arguments.
(this option is available for i386 machine now.)
--enable-dlstack use a stack emulation for constructing function call.
EOF
exit(0)
end
($CPPFLAGS || $CFLAGS) << " -I."
if (Config::CONFIG['CC'] =~ /gcc/) # from Win32API
$CFLAGS << " -fno-defer-pop -fno-omit-frame-pointer"
end
$with_dlstack ||= true
$with_asm = ! $with_dlstack
$with_type_int = try_cpp(<<EOF)
#include "config.h"
#if SIZEOF_INT == SIZEOF_LONG
#error int not needed
#endif
EOF
$with_type_float = try_cpp(<<EOF)
#include "config.h"
#if SIZEOF_FLOAT == SIZEOF_DOUBLE
#error float not needed
#endif
EOF
$with_type_voidp = try_cpp(<<EOF)
#include "config.h"
#if SIZEOF_VOIDP == SIZEOF_INT || SIZEOF_VOIDP == SIZEOF_LONG
#error void* not needed
#endif
EOF
$with_type_char = DLTYPE[CHAR][:sym]
$with_type_short = DLTYPE[SHORT][:sym]
$with_type_long = DLTYPE[LONG][:sym]
$with_type_double= DLTYPE[DOUBLE][:sym]
$with_type_int &= DLTYPE[INT][:sym]
$with_type_float &= DLTYPE[FLOAT][:sym]
$with_type_voidp &= DLTYPE[VOIDP][:sym]
$with_type_char = enable_config("type-char", $with_type_char)
$with_type_short = enable_config("type-short", $with_type_short)
$with_type_float = enable_config("type-float", $with_type_float)
$with_asm = enable_config("asm", $with_asm)
$with_dlstack = enable_config("dlstack", $with_dlstack)
args = with_config("args")
max_arg = nil
if( $with_asm || $with_dlstack )
$with_type_char = true
$with_type_short = true
$with_type_float = true
max_arg = 0
end
if( args )
max_arg = args.to_i
if( !max_arg )
print("--with-args=<max_arg>\n")
exit(1)
end
end
max_arg ||= 6
max_callback = with_config("callback","10").to_i
callback_types = DLTYPE.keys.length
$dlconfig_h = <<EOF
#define MAX_ARG #{max_arg}
EOF
def dlc_define(const)
$dlconfig_h << "#if !defined(#{const})\n" +
"# define #{const}\n" +
"#endif\n"
end
$dlconfig_h << "#define MAX_CALLBACK #{max_callback}\n"
$dlconfig_h << "#define CALLBACK_TYPES #{callback_types}\n"
if( $with_dlstack )
$dlconfig_h << "#define USE_DLSTACK\n"
else
if( $with_asm )
$dlconfig_h << "#define USE_INLINE_ASM\n"
end
end
if( $with_type_char )
$dlconfig_h << "#define WITH_TYPE_CHAR\n"
end
if( $with_type_short )
$dlconfig_h << "#define WITH_TYPE_SHORT\n"
end
if( $with_type_long )
$dlconfig_h << "#define WITH_TYPE_LONG\n"
end
if( $with_type_double )
$dlconfig_h << "#define WITH_TYPE_DOUBLE\n"
end
if( $with_type_float )
$dlconfig_h << "#define WITH_TYPE_FLOAT\n"
end
if( $with_type_int )
$dlconfig_h << "#define WITH_TYPE_INT\n"
end
if( $with_type_voidp )
$dlconfig_h << "#define WITH_TYPE_VOIDP\n"
end
if( have_header("windows.h") )
have_library("kernel32")
have_func("GetLastError", "windows.h")
dlc_define("HAVE_WINDOWS_H")
have_windows_h = true
end
if( have_header("dlfcn.h") )
dlc_define("HAVE_DLFCN_H")
have_library("dl")
have_func("dlopen")
have_func("dlclose")
have_func("dlsym")
if( have_func("dlerror") )
dlc_define("HAVE_DLERROR")
end
elsif ( have_windows_h )
have_func("LoadLibrary")
have_func("FreeLibrary")
have_func("GetProcAddress")
else
exit(0)
end
def File.update(file, str)
begin
open(file){|f|f.read} == str
rescue Errno::ENOENT
false
end or open(file, "w"){|f|f.print(str)}
end
File.update("dlconfig.h", <<EOF)
#ifndef DLCONFIG_H
#define DLCONFIG_H
#{$dlconfig_h}
#endif /* DLCONFIG_H */
EOF
File.update("dlconfig.rb", <<EOF)
MAX_ARG = #{max_arg}
MAX_CALLBACK = #{max_callback}
CALLBACK_TYPES = #{callback_types}
DLTYPE[CHAR][:sym] = #{$with_type_char}
DLTYPE[SHORT][:sym] = #{$with_type_short}
DLTYPE[INT][:sym] = #{$with_type_int}
DLTYPE[LONG][:sym] = #{$with_type_long}
DLTYPE[FLOAT][:sym] = #{$with_type_float}
DLTYPE[DOUBLE][:sym]= #{$with_type_double}
DLTYPE[VOIDP][:sym] = #{$with_type_voidp}
EOF
$INSTALLFILES = [
["./dlconfig.h", "$(archdir)$(target_prefix)", "."],
["dl.h", "$(archdir)$(target_prefix)", ""],
]
$cleanfiles = %w[test/test.o]
$distcleanfiles = %w[call.func callback.func cbtable.func dlconfig.rb
./dlconfig.h test/libtest.so test/*~ *~ mkmf.log]
create_makefile('dl')
rescue SystemExit
# do nothing
end

View file

@ -1,500 +0,0 @@
#!/usr/bin/env ruby
# -*- ruby -*-
# $Id$
require 'mkmf'
require 'ftools'
$recursive = false
$force = false
$conly = true
$inc_path = []
$infilename= nil
$insert_require = true
def valid_ruby_code?(code)
begin
eval("BEGIN {return true}; #{code}")
rescue SyntaxError
return false
end
return false
end
def print_usage
print <<EOF
h2rb [-r] [-I <path>] [-d] [<filename>]
EOF
end
while( ARGV[0] )
case( ARGV[0] )
when "-r"
ARGV.shift
$recursive = true
when "-R"
ARGV.shift
$recursive = false
when "-l"
ARGV.shift
$insert_require = true
when "-L"
ARGV.shift
$insert_require = false
when "-c"
ARGV.shift
$conly = true
when "-C"
ARGV.shift
$conly = false
when "-f"
ARGV.shift
$force = true
when "-F"
ARGV.shift
$force = false
when "-I"
ARGV.shift
$inc_path << ARGV.shift
when "-d"
ARGV.shift
$DEBUG = true
when "-h","--help"
print_usage()
exit 0
when /-.*/
$stderr.print("unknown option '#{ARGV[0]}'.\n")
print_usage()
exit 0
else
$infilename = ARGV.shift
end
end
$inc_dir = File.join(CONFIG["prefix"], "lib", "ruby",
CONFIG["MAJOR"] + "." + CONFIG["MINOR"],
"dl")
class H2RBError < StandardError; end
class H2RB
def initialize(inc_dir = nil, inc_path = nil, insert_require = nil)
@inc_path = inc_path || []
@inc_dir = inc_dir || '.'
@indent = 0
@parsed_files = []
@insert_require = insert_require || false
end
def find_path(file)
if( ! file )
return nil
end
if( File.exist?(file) )
if( file[0] == ?/ )
return file
else
return file
end
end
@inc_path.each{|path|
full = File.join(path, file)
if( File.exist?(full) )
return full
end
}
return nil
end
def strip_comment(line)
if( @commented )
if( e = line.index("*/") )
line[0..(e+1)] = ""
@commented = false
else
line = ""
end
else
if( s = line.index("/*") )
if( e = line.index("*/") )
line[s..(e+1)] = ""
else
line[s..-1] = ""
@commented = true
end
elsif( s = line.index("//") )
line[s..(-1)] = ""
end
end
line.gsub!(/\s+$/,"")
return line
end
def up_indent
@indent += 1
end
def down_indent
@indent -= 1
if( @indent < 0 )
raise
end
end
def indent
" " * @indent
end
def rescue_begin
line = "#{indent}begin"
up_indent
return line
end
def rescue_nameerror
down_indent
line = [
"#{indent}rescue NameError => e",
"#{indent} raise e if( $DEBUG )",
"#{indent}end"].join($/)
return line
end
def parse_enum(line)
if( line =~ /enum\s+(\S+\s+)?\{(.+)\}/ )
enum_name = $1
enum_block = $2
if( enum_name )
line = "#{indent}# -- enum #{enum_name}\n"
else
line = "#{indent}# -- enum\n"
end
enums = enum_block.split(/,/).collect{|e| e.strip}
i = 0
enums.each{|elem|
var,val = elem.split(/=/).collect{|e| e.strip}
if( val )
i = val.to_i
end
line += "#{indent}#{var} = #{i.to_s}\n"
i += 1
}
line += "#{indent}# -- end of enum"
return line
else
return nil
end
end
def parse_define(line)
case line
when /^#\s*define\s+(\S+)\(\)/
line = nil
when /^#\s*define\s+(\S+)\((.+)\)\s+(.+)$/
if( @conly )
line = nil
else
defname = $1
defargs = $2
defval = $3
if( !valid_ruby_code?(defval) )
defval = "nil # #{defval}"
end
if( defname[0,1] =~ /^[A-Z]$/ )
line = "#{indent}#{defname} = proc{|#{defargs}| #{defval}}"
else
line = [
"#{indent}def #{defname}(#{defargs})",
"#{indent} #{defval}",
"#{indent}end"
].join("\n")
end
end
when /^#\s*define\s+(\S+)\((.+)\)$/
if( @conly )
line = nil
else
defname = $1
defargs = $2
defval = nil
if( !valid_ruby_code?(defval) )
defval = "nil # #{defval}"
end
if( defname[0,1] =~ /^[A-Z]$/ )
line = "#{indent}#{defname} = proc{|#{defargs}| #{defval}}"
else
line = [
"#{indent}def #{defname}(#{defargs})",
"#{indent} #{defval}",
"#{indent}end"
].join("\n")
end
end
when /^#\s*define\s+(\S+)\s+(.+)$/
defname = $1
defval = $2
if( !valid_ruby_code?(defval) )
defval = "nil # #{defval}"
end
line = [rescue_begin, "#{indent}#{defname} = #{defval}", rescue_nameerror].join($/)
when /^#\s*define\s+(\S+)$/
defname = $1
line = "#{indent}#{defname} = nil"
else
line = nil
end
return line
end
def parse_undef(line)
case line
when /^#\s*undef\s+([A-Z]\S+)$/
defname = $1
line = "#{indent}remove_const(:#{defname})"
when /^#\s*undef\s+(\S+)$/
defname = $1
line = "#{indent}#{defname} = nil"
else
line = nil
end
return line
end
def parse_ifdef(line)
case line
when /^#\s*ifdef\s+(\S+)$/
defname = $1
line = [
rescue_begin,
"#{indent}if( defined?(#{defname}) && ! #{defname}.nil? )"].join($/)
else
line = nil
end
return line
end
def parse_ifndef(line)
case line
when /^#\s*ifndef\s+(\S+)$/
defname = $1
line = [
rescue_begin,
"#{indent}if( ! defined?(#{defname}) || #{defname}.nil? )"].join($/)
else
line = nil
end
return line
end
def parse_if(line)
case line
when /^#\s*if\s+(.+)$/
cond = $1
cond.gsub!(/defined(.+)/){ "defined?(#{$1}) && ! #{$1}.nil?" }
if( valid_ruby_code?(cond) )
line = "#{indent}if( #{cond} )"
else
line = "#{indent}if( false ) # #{cond}"
end
line = [rescue_begin, line].join($/)
else
line = nil
end
return line
end
def parse_elif(line)
case line
when /^#\s*elif\s+(.+)$/
cond = $1
cond.gsub!("defined","defined?")
line = "#{indent}elsif( #{cond} )"
else
line = nil
end
return line
end
def parse_else(line)
case line
when /^#\s*else\s*/
line = "#{indent}else"
else
line = nil
end
return line
end
def parse_endif(line)
case line
when /^#\s*endif\s*$/
line = ["#{indent}end", rescue_nameerror].join($/)
else
line = nil
end
return line
end
def parse_include(line)
if( ! @insert_require )
return nil
end
file = nil
case line
when /^#\s*include "(.+)"$/
file = $1
line = "#{indent}require '#{file}'"
when /^#\s*include \<(.+)\>$/
file = $1
line = "#{indent}require '#{file}'"
else
line = nil
end
if( @recursive && file && (!@parsed_files.include?(file)) )
parse(file, @recursive, @force, @conly)
end
return line
end
def open_files(infilename)
if( ! infilename )
return [$stdin, $stdout]
end
old_infilename = infilename
infilename = find_path(infilename)
if( ! infilename )
$stderr.print("'#{old_infilename}' was not found.\n")
return [nil,nil]
end
if( infilename )
if( infilename[0,1] == '/' )
outfilename = File.join(@inc_dir, infilename[1..-1] + ".rb")
else
outfilename = infilename + ".rb"
end
File.mkpath(File.dirname(outfilename))
else
outfilename = nil
end
if( infilename )
fin = File.open(infilename,"r")
else
fin = $stdin
end
if( outfilename )
if( File.exist?(outfilename) && (!@force) )
$stderr.print("'#{outfilename}' have already existed.\n")
return [fin, nil]
end
fout = File.open(outfilename,"w")
else
fout = $stdout
end
$stderr.print("#{infilename} -> #{outfilename}\n")
if( fout )
dir = File.dirname(outfilename)
if( dir[0,1] != "." && dir != "" )
fout.print("if( ! $LOAD_PATH.include?('#{dir}') )\n",
" $LOAD_PATH.push('#{dir}')\n",
"end\n")
end
end
return [fin,fout]
end
def parse(infilename = nil, recursive = false, force = false, conly = false)
@commented = false
@recursive = recursive
@force = force
@conly = conly
@parsed_files << infilename
fin,fout = open_files(infilename)
if( !fin )
return
end
begin
line_number = 0
pre_line = nil
fin.each_line{|line|
line_number += 1
line.chop!
if( $DEBUG )
$stderr.print("#{line_number}:(#{@indent}):", line, "\n")
end
if( pre_line )
line = pre_line + line
pre_line = nil
end
if( line[-1,1] == "\\" )
pre_line = line[0..-2]
next
end
if( eidx = line.index("enum ") )
pre_line = line[eidx .. -1]
if( i = line.index("{") && j = line.index("}") )
line = line[0..j]
pre_line = nil
else
next
end
end
line = strip_comment(line)
case line
when /^enum\s/
line = parse_enum(line)
when /^#\s*define\s/
line = parse_define(line)
when /^#\s*undef\s/
line = parse_undef(line)
when /^#\s*ifdef\s/
line = parse_ifdef(line)
up_indent
when /^#\s*ifndef\s/
line = parse_ifndef(line)
up_indent
when /^#\s*if\s/
line = parse_if(line)
up_indent
when /^#\s*elif\s/
down_indent
line = parse_elif(line)
up_indent
when /^#\s*else/
down_indent
line = parse_else(line)
up_indent
when /^#\s*endif/
down_indent
line = parse_endif(line)
when /^#\s*include\s/
line = parse_include(line)
else
line = nil
end
if( line && fout )
fout.print(line, " # #{line_number}",$/)
end
}
ensure
fin.close if fin
fout.close if fout
end
end
end
h2rb = H2RB.new($inc_dir, $inc_path, $insert_require)
h2rb.parse($infilename, $recursive, $force, $conly)

View file

@ -1,215 +0,0 @@
/* -*- mode: C; c-file-style: "gnu" -*-
* $Id$
*/
#include <ruby.h>
#include "dl.h"
VALUE rb_cDLHandle;
void
dlhandle_free(struct dl_handle *dlhandle)
{
if (dlhandle->ptr && dlhandle->open && dlhandle->enable_close) {
dlclose(dlhandle->ptr);
}
}
VALUE
rb_dlhandle_close(VALUE self)
{
struct dl_handle *dlhandle;
Data_Get_Struct(self, struct dl_handle, dlhandle);
dlhandle->open = 0;
return INT2NUM(dlclose(dlhandle->ptr));
}
VALUE
rb_dlhandle_s_allocate(VALUE klass)
{
VALUE obj;
struct dl_handle *dlhandle;
obj = Data_Make_Struct(rb_cDLHandle, struct dl_handle, 0,
dlhandle_free, dlhandle);
dlhandle->ptr = 0;
dlhandle->open = 0;
dlhandle->enable_close = 0;
return obj;
}
VALUE
rb_dlhandle_initialize(int argc, VALUE argv[], VALUE self)
{
void *ptr;
struct dl_handle *dlhandle;
VALUE lib, flag;
char *clib;
int cflag;
const char *err;
switch (rb_scan_args(argc, argv, "11", &lib, &flag)) {
case 1:
clib = NIL_P(lib) ? NULL : StringValuePtr(lib);
cflag = RTLD_LAZY | RTLD_GLOBAL;
break;
case 2:
clib = NIL_P(lib) ? NULL : StringValuePtr(lib);
cflag = NUM2INT(flag);
break;
default:
rb_bug("rb_dlhandle_new");
}
ptr = dlopen(clib, cflag);
#if defined(HAVE_DLERROR)
if (!ptr && (err = dlerror())) {
rb_raise(rb_eRuntimeError, err);
}
#else
if (!ptr) {
err = dlerror();
rb_raise(rb_eRuntimeError, err);
}
#endif
Data_Get_Struct(self, struct dl_handle, dlhandle);
if (dlhandle->ptr && dlhandle->open && dlhandle->enable_close) {
dlclose(dlhandle->ptr);
}
dlhandle->ptr = ptr;
dlhandle->open = 1;
dlhandle->enable_close = 0;
if (rb_block_given_p()) {
rb_ensure(rb_yield, self, rb_dlhandle_close, self);
}
return Qnil;
}
VALUE
rb_dlhandle_enable_close(VALUE self)
{
struct dl_handle *dlhandle;
Data_Get_Struct(self, struct dl_handle, dlhandle);
dlhandle->enable_close = 1;
return Qnil;
}
VALUE
rb_dlhandle_disable_close(VALUE self)
{
struct dl_handle *dlhandle;
Data_Get_Struct(self, struct dl_handle, dlhandle);
dlhandle->enable_close = 0;
return Qnil;
}
VALUE
rb_dlhandle_to_i(VALUE self)
{
struct dl_handle *dlhandle;
Data_Get_Struct(self, struct dl_handle, dlhandle);
return DLLONG2NUM(dlhandle);
}
VALUE
rb_dlhandle_to_ptr(VALUE self)
{
struct dl_handle *dlhandle;
Data_Get_Struct(self, struct dl_handle, dlhandle);
return rb_dlptr_new(dlhandle, sizeof(dlhandle), 0);
}
VALUE
rb_dlhandle_sym(int argc, VALUE argv[], VALUE self)
{
VALUE sym, type;
void (*func)();
VALUE val;
struct dl_handle *dlhandle;
void *handle;
const char *name, *stype;
const char *err;
rb_secure(2);
if (rb_scan_args(argc, argv, "11", &sym, &type) == 2) {
SafeStringValue(type);
stype = StringValuePtr(type);
}
else{
stype = NULL;
}
if (sym == Qnil) {
#if defined(RTLD_NEXT)
name = RTLD_NEXT;
#else
name = NULL;
#endif
}
else{
SafeStringValue(sym);
name = StringValuePtr(sym);
}
Data_Get_Struct(self, struct dl_handle, dlhandle);
if (!dlhandle->open) {
rb_raise(rb_eRuntimeError, "Closed handle.");
}
handle = dlhandle->ptr;
func = dlsym(handle, name);
#if defined(HAVE_DLERROR)
if (!func && (err = dlerror()))
#else
if (!func)
#endif
{
#if defined(__CYGWIN__) || defined(WIN32) || defined(__MINGW32__)
{
int len = strlen(name);
char *name_a = (char*)dlmalloc(len+2);
strcpy(name_a, name);
name_a[len] = 'A';
name_a[len+1] = '\0';
func = dlsym(handle, name_a);
dlfree(name_a);
#if defined(HAVE_DLERROR)
if (!func && (err = dlerror()))
#else
if (!func)
#endif
{
rb_raise(rb_eRuntimeError, "Unknown symbol \"%sA\".", name);
}
}
#else
rb_raise(rb_eRuntimeError, "Unknown symbol \"%s\".", name);
#endif
}
val = rb_dlsym_new(func, name, stype);
return val;
}
void
Init_dlhandle()
{
rb_cDLHandle = rb_define_class_under(rb_mDL, "Handle", rb_cObject);
rb_define_alloc_func(rb_cDLHandle, rb_dlhandle_s_allocate);
rb_define_method(rb_cDLHandle, "initialize", rb_dlhandle_initialize, -1);
rb_define_method(rb_cDLHandle, "to_i", rb_dlhandle_to_i, 0);
rb_define_method(rb_cDLHandle, "to_ptr", rb_dlhandle_to_ptr, 0);
rb_define_method(rb_cDLHandle, "close", rb_dlhandle_close, 0);
rb_define_method(rb_cDLHandle, "sym", rb_dlhandle_sym, -1);
rb_define_method(rb_cDLHandle, "[]", rb_dlhandle_sym, -1);
rb_define_method(rb_cDLHandle, "disable_close", rb_dlhandle_disable_close, 0);
rb_define_method(rb_cDLHandle, "enable_close", rb_dlhandle_enable_close, 0);
}

View file

@ -1,49 +0,0 @@
require 'mkmf'
require 'ftools'
SO_LIBS = ["dl.so"]
$ruby_version = CONFIG['MAJOR'] + "." + CONFIG['MINOR']
$prefix = CONFIG['prefix']
$libdir = File.join($prefix,'lib')
$rubylibdir = File.join($libdir, 'ruby', $ruby_version)
$arch = CONFIG['arch']
$archdir = File.join($rubylibdir, $arch)
def find(dir, match = /./)
Dir.chdir(dir)
files = []
Dir.new(".").each{|file|
if( file != "." && file != ".." )
case File.ftype(file)
when "file"
if( file =~ match )
files.push(File.join(dir,file))
end
when "directory"
files += find(file, match).collect{|f| File.join(dir,f)}
end
end
}
Dir.chdir("..")
return files
end
def install()
rb_files = find(File.join(".","lib"), /.rb$/)
SO_LIBS.each{|f|
File.makedirs($rubylibdir, "#{$archdir}")
File.install(f, File.join($archdir,f), 0555, true)
}
rb_files.each{|f|
origfile = f
instfile = File.join($rubylibdir, origfile.sub("./lib/",""))
instdir = File.dirname(instfile)
File.makedirs(instdir)
File.install(origfile, instfile, 0644, true)
}
end
install()

View file

@ -1,224 +0,0 @@
# -*- ruby -*-
require 'dl'
require 'dl/types'
module DL
module Importable
LIB_MAP = {}
module Internal
def init_types()
@types ||= ::DL::Types.new
end
def init_sym()
@SYM ||= {}
end
def [](name)
return @SYM[name.to_s][0]
end
def dlload(*libnames)
if( !defined?(@LIBS) )
@LIBS = []
end
libnames.each{|libname|
if( !LIB_MAP[libname] )
LIB_MAP[libname] = DL.dlopen(libname)
end
@LIBS.push(LIB_MAP[libname])
}
end
alias dllink :dlload
def parse_cproto(proto)
proto = proto.gsub(/\s+/, " ").strip
case proto
when /^([\d\w\*_\s]+)\(([\d\w\*_\s\,\[\]]*)\)$/
ret = $1
args = $2
ret = ret.split(/\s+/)
args = args.split(/\s*,\s*/)
func = ret.pop
if( func =~ /^\*/ )
func.gsub!(/^\*+/,"")
ret.push("*")
end
ret = ret.join(" ")
return [func, ret, args]
else
raise(RuntimeError,"can't parse the function prototype: #{proto}")
end
end
# example:
# extern "int strlen(char*)"
#
def extern(proto)
func,ret,args = parse_cproto(proto)
return import(func, ret, args)
end
# example:
# callback "int method_name(int, char*)"
#
def callback(proto)
func,ret,args = parse_cproto(proto)
init_types()
init_sym()
rty,renc,rdec = @types.encode_return_type(ret)
if( !rty )
raise(TypeError, "unsupported type: #{ret}")
end
ty,enc,dec = encode_argument_types(args)
symty = rty + ty
module_eval("module_function :#{func}")
sym = module_eval([
"DL::callback(\"#{symty}\"){|*args|",
" sym,rdec,enc,dec = @SYM['#{func}']",
" args = enc.call(args) if enc",
" r,rs = #{func}(*args)",
" r = renc.call(r) if rdec",
" rs = dec.call(rs) if (dec && rs)",
" @retval = r",
" @args = rs",
" @retval",
"}",
].join("\n"))
@SYM[func] = [sym,rdec,enc,dec]
return sym
end
# example:
# typealias("uint", "unsigned int")
#
def typealias(*args)
init_types()
@types.typealias(*args)
end
# example:
# symbol "foo_value"
# symbol "foo_func", "IIP"
#
def symbol(name, ty = nil)
sym = nil
@LIBS.each{|lib|
begin
if( ty )
sym = lib[name, ty]
else
sym = lib[name]
end
rescue
next
end
}
if( !sym )
raise(RuntimeError, "can't find the symbol `#{name}'")
end
return sym
end
# example:
# import("get_length", "int", ["void*", "int"])
#
def import(name, rettype, argtypes = nil)
init_types()
init_sym()
rty,_,rdec = @types.encode_return_type(rettype)
if( !rty )
raise(TypeError, "unsupported type: #{rettype}")
end
ty,enc,dec = encode_argument_types(argtypes)
symty = rty + ty
sym = symbol(name, symty)
mname = name.dup
if( ?A <= mname[0] && mname[0] <= ?Z )
mname[0,1] = mname[0,1].downcase
end
@SYM[mname] = [sym,rdec,enc,dec]
module_eval [
"def #{mname}(*args)",
" sym,rdec,enc,dec = @SYM['#{mname}']",
" args = enc.call(args) if enc",
if( $DEBUG )
" p \"[DL] call #{mname} with \#{args.inspect}\""
else
""
end,
" r,rs = sym.call(*args)",
if( $DEBUG )
" p \"[DL] retval=\#{r.inspect} args=\#{rs.inspect}\""
else
""
end,
" r = rdec.call(r) if rdec",
" rs = dec.call(rs) if dec",
" @retval = r",
" @args = rs",
" return @retval",
"end",
"module_function :#{mname}",
].join("\n")
return sym
end
def _args_
return @args
end
def _retval_
return @retval
end
def encode_argument_types(tys)
init_types()
encty = []
enc = nil
dec = nil
tys.each_with_index{|ty,idx|
ty,c1,c2 = @types.encode_argument_type(ty)
if( !ty )
raise(TypeError, "unsupported type: #{ty}")
end
encty.push(ty)
if( enc )
if( c1 )
conv1 = enc
enc = proc{|v| v = conv1.call(v); v[idx] = c1.call(v[idx]); v}
end
else
if( c1 )
enc = proc{|v| v[idx] = c1.call(v[idx]); v}
end
end
if( dec )
if( c2 )
conv2 = dec
dec = proc{|v| v = conv2.call(v); v[idx] = c2.call(v[idx]); v}
end
else
if( c2 )
dec = proc{|v| v[idx] = c2.call(v[idx]); v}
end
end
}
return [encty.join, enc, dec]
end
end # end of Internal
include Internal
end # end of Importable
end

View file

@ -1,149 +0,0 @@
# -*- ruby -*-
require 'dl'
require 'dl/import'
module DL
module Importable
module Internal
def define_struct(contents)
init_types()
Struct.new(@types, contents)
end
alias struct define_struct
def define_union(contents)
init_types()
Union.new(@types, contents)
end
alias union define_union
class Memory
def initialize(ptr, names, ty, len, enc, dec)
@ptr = ptr
@names = names
@ty = ty
@len = len
@enc = enc
@dec = dec
# define methods
@names.each{|name|
instance_eval [
"def #{name}",
" v = @ptr[\"#{name}\"]",
" if( @len[\"#{name}\"] )",
" v = v.collect{|x| @dec[\"#{name}\"] ? @dec[\"#{name}\"].call(x) : x }",
" else",
" v = @dec[\"#{name}\"].call(v) if @dec[\"#{name}\"]",
" end",
" return v",
"end",
"def #{name}=(v)",
" if( @len[\"#{name}\"] )",
" v = v.collect{|x| @enc[\"#{name}\"] ? @enc[\"#{name}\"].call(x) : x }",
" else",
" v = @enc[\"#{name}\"].call(v) if @enc[\"#{name}\"]",
" end",
" @ptr[\"#{name}\"] = v",
" return v",
"end",
].join("\n")
}
end
def to_ptr
return @ptr
end
def size
return @ptr.size
end
end
class Struct
def initialize(types, contents)
@names = []
@ty = {}
@len = {}
@enc = {}
@dec = {}
@size = 0
@tys = ""
@types = types
parse(contents)
end
def size
return @size
end
def members
return @names
end
# ptr must be a PtrData object.
def new(ptr)
ptr.struct!(@tys, *@names)
mem = Memory.new(ptr, @names, @ty, @len, @enc, @dec)
return mem
end
def malloc(size = nil)
if( !size )
size = @size
end
ptr = DL::malloc(size)
return new(ptr)
end
def parse(contents)
contents.each{|elem|
name,ty,num,enc,dec = parse_elem(elem)
@names.push(name)
@ty[name] = ty
@len[name] = num
@enc[name] = enc
@dec[name] = dec
if( num )
@tys += "#{ty}#{num}"
else
@tys += ty
end
}
@size = DL.sizeof(@tys)
end
def parse_elem(elem)
elem.strip!
case elem
when /^([\w\d_\*]+)([\*\s]+)([\w\d_]+)$/
ty = ($1 + $2).strip
name = $3
num = nil;
when /^([\w\d_\*]+)([\*\s]+)([\w\d_]+)\[(\d+)\]$/
ty = ($1 + $2).strip
name = $3
num = $4.to_i
else
raise(RuntimeError, "invalid element: #{elem}")
end
ty,enc,dec = @types.encode_struct_type(ty)
if( !ty )
raise(TypeError, "unsupported type: #{ty}")
end
return [name,ty,num,enc,dec]
end
end # class Struct
class Union < Struct
def new
ptr = DL::malloc(@size)
ptr.union!(@tys, *@names)
mem = Memory.new(ptr, @names, @ty, @len, @enc, @dec)
return mem
end
end
end # module Internal
end # module Importable
end # module DL

View file

@ -1,245 +0,0 @@
# -*- ruby -*-
require 'dl'
module DL
class Types
TYPES = [
# FORMAT:
# ["alias name",
# "type name", encoding_method, decoding_method, for function prototypes
# "type name", encoding_method, decoding_method] for structures (not implemented)
# for Windows
["DWORD", "unsigned long", nil, nil,
"unsigned long", nil, nil],
["PDWORD", "unsigned long *", nil, nil,
"unsigned long *", nil, nil],
["WORD", "unsigned short", nil, nil,
"unsigned short", nil, nil],
["PWORD", "unsigned int *", nil, nil,
"unsigned int *", nil, nil],
["BYTE", "unsigned char", nil, nil,
"unsigned char", nil, nil],
["PBYTE", "unsigned char *", nil, nil,
"unsigned char *", nil, nil],
["BOOL", "ibool", nil, nil,
"ibool", nil, nil],
["ATOM", "int", nil, nil,
"int", nil, nil],
["BYTE", "unsigned char", nil, nil,
"unsigned char", nil, nil],
["PBYTE", "unsigned char *", nil, nil,
"unsigned char *", nil, nil],
["UINT", "unsigned int", nil, nil,
"unsigned int", nil, nil],
["ULONG", "unsigned long", nil, nil,
"unsigned long", nil, nil],
["UCHAR", "unsigned char", nil, nil,
"unsigned char", nil, nil],
["HANDLE", "unsigned long", nil, nil,
"unsigned long", nil, nil],
["PHANDLE","void*", nil, nil,
"void*", nil, nil],
["PVOID", "void*", nil, nil,
"void*", nil, nil],
["LPCSTR", "char*", nil, nil,
"char*", nil, nil],
["HDC", "unsigned int", nil, nil,
"unsigned int", nil, nil],
["HWND", "unsigned int", nil, nil,
"unsigned int", nil, nil],
# Others
["uint", "unsigned int", nil, nil,
"unsigned int", nil, nil],
["u_int", "unsigned int", nil, nil,
"unsigned int", nil, nil],
["ulong", "unsigned long", nil, nil,
"unsigned long", nil, nil],
["u_long", "unsigned long", nil, nil,
"unsigned long", nil, nil],
# DL::Importable primitive types
["ibool",
"I",
proc{|v| v ? 1 : 0},
proc{|v| (v != 0) ? true : false},
"I",
proc{|v| v ? 1 : 0 },
proc{|v| (v != 0) ? true : false} ],
["cbool",
"C",
proc{|v| v ? 1 : 0},
proc{|v| (v != 0) ? true : false},
"C",
proc{|v,len| v ? 1 : 0},
proc{|v,len| (v != 0) ? true : false}],
["lbool",
"L",
proc{|v| v ? 1 : 0},
proc{|v| (v != 0) ? true : false},
"L",
proc{|v,len| v ? 1 : 0},
proc{|v,len| (v != 0) ? true : false}],
["unsigned char",
"C",
proc{|v| [v].pack("C").unpack("c")[0]},
proc{|v| [v].pack("c").unpack("C")[0]},
"C",
proc{|v| [v].pack("C").unpack("c")[0]},
proc{|v| [v].pack("c").unpack("C")[0]}],
["unsigned short",
"H",
proc{|v| [v].pack("S").unpack("s")[0]},
proc{|v| [v].pack("s").unpack("S")[0]},
"H",
proc{|v| [v].pack("S").unpack("s")[0]},
proc{|v| [v].pack("s").unpack("S")[0]}],
["unsigned int",
"I",
proc{|v| [v].pack("I").unpack("i")[0]},
proc{|v| [v].pack("i").unpack("I")[0]},
"I",
proc{|v| [v].pack("I").unpack("i")[0]},
proc{|v| [v].pack("i").unpack("I")[0]}],
["unsigned long",
"L",
proc{|v| [v].pack("L").unpack("l")[0]},
proc{|v| [v].pack("l").unpack("L")[0]},
"L",
proc{|v| [v].pack("L").unpack("l")[0]},
proc{|v| [v].pack("l").unpack("L")[0]}],
["unsigned char ref",
"c",
proc{|v| [v].pack("C").unpack("c")[0]},
proc{|v| [v].pack("c").unpack("C")[0]},
nil, nil, nil],
["unsigned int ref",
"i",
proc{|v| [v].pack("I").unpack("i")[0]},
proc{|v| [v].pack("i").unpack("I")[0]},
nil, nil, nil],
["unsigned long ref",
"l",
proc{|v| [v].pack("L").unpack("l")[0]},
proc{|v| [v].pack("l").unpack("L")[0]},
nil, nil, nil],
["char ref", "c", nil, nil,
nil, nil, nil],
["short ref", "h", nil, nil,
nil, nil, nil],
["int ref", "i", nil, nil,
nil, nil, nil],
["long ref", "l", nil, nil,
nil, nil, nil],
["float ref", "f", nil, nil,
nil, nil, nil],
["double ref","d", nil, nil,
nil, nil, nil],
["char", "C", nil, nil,
"C", nil, nil],
["short", "H", nil, nil,
"H", nil, nil],
["int", "I", nil, nil,
"I", nil, nil],
["long", "L", nil, nil,
"L", nil, nil],
["float", "F", nil, nil,
"F", nil, nil],
["double", "D", nil, nil,
"D", nil, nil],
[/^char\s*\*$/,"s",nil, nil,
"S",nil, nil],
[/^const char\s*\*$/,"S",nil, nil,
"S",nil, nil],
[/^.+\*$/, "P", nil, nil,
"P", nil, nil],
[/^.+\[\]$/, "a", nil, nil,
"a", nil, nil],
["void", "0", nil, nil,
nil, nil, nil],
]
def initialize
init_types()
end
def typealias(ty1, ty2, enc=nil, dec=nil, ty3=nil, senc=nil, sdec=nil)
@TYDEFS.unshift([ty1, ty2, enc, dec, ty3, senc, sdec])
end
def init_types
@TYDEFS = TYPES.dup
end
def encode_argument_type(alias_type)
proc_encode = nil
proc_decode = nil
@TYDEFS.each{|aty,ty,enc,dec,_,_,_|
if( (aty.is_a?(Regexp) && (aty =~ alias_type)) || (aty == alias_type) )
alias_type = alias_type.gsub(aty,ty) if ty
alias_type.strip! if alias_type
if( proc_encode )
if( enc )
conv1 = proc_encode
proc_encode = proc{|v| enc.call(conv1.call(v))}
end
else
if( enc )
proc_encode = enc
end
end
if( proc_decode )
if( dec )
conv2 = proc_decode
proc_decode = proc{|v| dec.call(conv2.call(v))}
end
else
if( dec )
proc_decode = dec
end
end
end
}
return [alias_type, proc_encode, proc_decode]
end
def encode_return_type(ty)
ty, enc, dec = encode_argument_type(ty)
return [ty, enc, dec]
end
def encode_struct_type(alias_type)
proc_encode = nil
proc_decode = nil
@TYDEFS.each{|aty,_,_,_,ty,enc,dec|
if( (aty.is_a?(Regexp) && (aty =~ alias_type)) || (aty == alias_type) )
alias_type = alias_type.gsub(aty,ty) if ty
alias_type.strip! if alias_type
if( proc_encode )
if( enc )
conv1 = proc_encode
proc_encode = proc{|v| enc.call(conv1.call(v))}
end
else
if( enc )
proc_encode = enc
end
end
if( proc_decode )
if( dec )
conv2 = proc_decode
proc_decode = proc{|v| dec.call(conv2.call(v))}
end
else
if( dec )
proc_decode = dec
end
end
end
}
return [alias_type, proc_encode, proc_decode]
end
end # end of Types
end

View file

@ -1,25 +0,0 @@
# -*- ruby -*-
require 'dl'
class Win32API
DLL = {}
def initialize(dllname, func, import, export = "0")
prototype = (export + import.to_s).tr("VPpNnLlIi", "0SSI")
handle = DLL[dllname] ||= DL::Handle.new(dllname)
@sym = handle.sym(func, prototype)
end
def call(*args)
import = @sym.proto.split("", 2)[1]
args.each_with_index do |x, i|
args[i] = nil if x == 0 and import[i] == ?S
args[i], = [x].pack("I").unpack("i") if import[i] == ?I
end
ret, = @sym.call(*args)
return ret || 0
end
alias Call call
end

View file

@ -1,62 +0,0 @@
# -*- ruby -*-
require 'mkmf'
$:.unshift File.dirname(__FILE__)
require 'type'
require 'dlconfig'
def output_arg(x,i)
"args[#{i}].#{DLTYPE[x][:stmem]}"
end
def output_args(types)
t = []
types[1..-1].each_with_index{|x,i| t.push(output_arg(x,i))}
t.join(",")
end
def output_callfunc(types)
t = types[0]
stmem = DLTYPE[t][:stmem]
ctypes = types2ctypes(types)
if( t == VOID )
callstm = "(*f)(#{output_args(types)})"
else
callstm = "ret.#{stmem} = (*f)(#{output_args(types)})"
end
[ "{",
"#{ctypes[0]} (*f)(#{ctypes[1..-1].join(',')}) = func;",
"#{callstm};",
"}"].join(" ")
end
def output_case(types)
num = types2num(types)
callfunc_stm = output_callfunc(types)
<<EOF
case #{num}:
#ifdef DEBUG
printf("#{callfunc_stm}\\n");
#endif
#{callfunc_stm};
break;
EOF
end
def rec_output(types = [VOID])
print output_case(types)
if( types.length <= MAX_ARG )
DLTYPE.keys.sort.each{|t|
if( t != VOID && DLTYPE[t][:sym] )
rec_output(types + [t])
end
}
end
end
DLTYPE.keys.sort.each{|t|
if( DLTYPE[t][:sym] )
$stderr.printf(" #{DLTYPE[t][:ctype]}\n")
rec_output([t])
end
}

View file

@ -1,53 +0,0 @@
# -*- ruby -*-
require 'mkmf'
$:.unshift File.dirname(__FILE__)
require 'type'
require 'dlconfig'
def mkfunc(rettype, fnum, argc)
args = (0..(argc-1)).collect{|i| "long arg#{i}"}.join(", ")
subst_code = (0..(argc-1)).collect{|i|
" buff[#{i.to_s}] = arg#{i.to_s};"
}.join("\n")
ret_code =
if( DLTYPE[rettype][:c2rb] )
" return #{DLTYPE[rettype][:rb2c]['retval']};"
else
" /* no return value */"
end
code = [
"static #{DLTYPE[rettype][:ctype]}",
"rb_dl_callback_func_#{rettype.to_s}_#{fnum.to_s}(#{args})",
"{",
" VALUE retval, proto, proc, obj;",
" VALUE argv[#{argc.to_s}];",
" int argc;",
" long buff[#{argc.to_s}];",
"",
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);",
" Check_Type(proto, T_STRING);",
" if( RSTRING(proto)->len >= #{argc.to_s} )",
" rb_raise(rb_eArgError, \"too many arguments\");",
" rb_dl_scan_callback_args(buff, RSTRING(proto)->ptr, &argc, argv);",
" retval = rb_funcall2(proc, id_call, argc, argv);",
"",
ret_code,
"}",
].join("\n")
return code
end
DLTYPE.keys.sort.each{|t|
for n in 0..(MAX_CALLBACK - 1)
print(mkfunc(t, n, 15), "\n\n")
end
}

View file

@ -1,18 +0,0 @@
# -*- ruby -*-
require 'mkmf'
$:.unshift File.dirname(__FILE__)
require 'type'
require 'dlconfig'
def mktable(rettype, fnum, argc)
code =
"rb_dl_callback_table[#{rettype}][#{fnum}] = &rb_dl_callback_func_#{rettype.to_s}_#{fnum};"
return code
end
DLTYPE.keys.sort.each{|t|
for n in 0..(MAX_CALLBACK - 1)
print(mktable(t, n, 15), "\n")
end
}

File diff suppressed because it is too large Load diff

View file

@ -1,35 +0,0 @@
#include <stdio.h>
class Person {
private:
const char *name;
int age;
public:
Person(const char *name, int age);
const char * get_name();
int get_age();
void set_age(int i);
};
Person::Person(const char *name, int age)
: name(name), age(age)
{
/* empty */
}
const char *
Person::get_name()
{
return name;
}
int
Person::get_age(){
return age;
}
void
Person::set_age(int i){
age = i;
}

View file

@ -1,60 +0,0 @@
=begin
This script shows how to deal with C++ classes using Ruby/DL.
You must build a dynamic loadable library using "c++sample.C"
to run this script as follows:
$ g++ -o libsample.so -shared c++sample.C
=end
require 'dl'
require 'dl/import'
require 'dl/struct'
# Give a name of dynamic loadable library
LIBNAME = ARGV[0] || "libsample.so"
class Person
module Core
extend DL::Importable
dlload LIBNAME
# mangled symbol names
extern "void __6PersonPCci(void *, const char *, int)"
extern "const char *get_name__6Person(void *)"
extern "int get_age__6Person(void *)"
extern "void set_age__6Personi(void *, int)"
Data = struct [
"char *name",
"int age",
]
end
def initialize(name, age)
@ptr = Core::Data.alloc
Core::__6PersonPCci(@ptr, name, age)
end
def get_name()
str = Core::get_name__6Person(@ptr)
if( str )
str.to_s
else
nil
end
end
def get_age()
Core::get_age__6Person(@ptr)
end
def set_age(age)
Core::set_age__6Personi(@ptr, age)
end
end
obj = Person.new("ttate", 1)
p obj.get_name()
p obj.get_age()
obj.set_age(10)
p obj.get_age()

View file

@ -1,70 +0,0 @@
# -*- ruby -*-
# drives.rb -- find existing drives and show the drive type.
require 'dl'
require 'dl/import'
module Kernel32
extend DL::Importable
dlload "kernel32"
extern "long GetLogicalDrives()"
extern "int GetDriveType(char*)"
extern "long GetDiskFreeSpace(char*, long ref, long ref, long ref, long ref)"
end
include Kernel32
buff = Kernel32.getLogicalDrives()
i = 0
ds = []
while( i < 26 )
mask = (1 << i)
if( buff & mask > 0 )
ds.push((65+i).chr)
end
i += 1
end
=begin
From the cygwin's /usr/include/w32api/winbase.h:
#define DRIVE_UNKNOWN 0
#define DRIVE_NO_ROOT_DIR 1
#define DRIVE_REMOVABLE 2
#define DRIVE_FIXED 3
#define DRIVE_REMOTE 4
#define DRIVE_CDROM 5
#define DRIVE_RAMDISK 6
=end
types = [
"unknown",
"no root dir",
"Removable",
"Fixed",
"Remote",
"CDROM",
"RAM",
]
print("Drive : Type (Free Space/Available Space)\n")
ds.each{|d|
t = Kernel32.getDriveType(d + ":\\")
Kernel32.getDiskFreeSpace(d + ":\\", 0, 0, 0, 0)
_,sec_per_clus,byte_per_sec,free_clus,total_clus = Kernel32._args_
fbytes = sec_per_clus * byte_per_sec * free_clus
tbytes = sec_per_clus * byte_per_sec * total_clus
unit = "B"
if( fbytes > 1024 && tbytes > 1024 )
fbytes = fbytes / 1024
tbytes = tbytes / 1024
unit = "K"
end
if( fbytes > 1024 && tbytes > 1024 )
fbytes = fbytes / 1024
tbytes = tbytes / 1024
unit = "M"
end
print("#{d} : #{types[t]} (#{fbytes} #{unit}/#{tbytes} #{unit})\n")
}

View file

@ -1,5 +0,0 @@
require 'dl'
crtdll = DL::dlopen("crtdll")
getch = crtdll['_getch', 'L']
print(getch.call, "\n")

View file

@ -1,69 +0,0 @@
require "dl/import"
require "dl/struct"
module LIBC
extend DL::Importable
begin
dlload "libc.so.6"
rescue
dlload "libc.so.5"
end
extern "int atoi(char*)"
extern "ibool isdigit(int)"
extern "int gettimeofday(struct timeval *, struct timezone *)"
extern "char* strcat(char*, char*)"
extern "FILE* fopen(char*, char*)"
extern "int fclose(FILE*)"
extern "int fgetc(FILE*)"
extern "int strlen(char*)"
extern "void qsort(void*, int, int, void*)"
def str_qsort(ary, comp)
len = ary.length
r,rs = qsort(ary, len, DL.sizeof('P'), comp)
return rs[0].to_a('S', len)
end
Timeval = struct [
"long tv_sec",
"long tv_usec",
]
Timezone = struct [
"int tz_minuteswest",
"int tz_dsttime",
]
def my_compare(ptr1, ptr2)
ptr1.ptr.to_s <=> ptr2.ptr.to_s
end
COMPARE = callback("int my_compare(char**, char**)")
end
$cb1 = DL.callback('IPP'){|ptr1, ptr2|
str1 = ptr1.ptr.to_s
str2 = ptr2.ptr.to_s
str1 <=> str2
}
p LIBC.atoi("10")
p LIBC.isdigit(?1)
p LIBC.isdigit(?a)
p LIBC.strcat("a", "b")
ary = ["a","c","b"]
ptr = ary.to_ptr
LIBC.qsort(ptr, ary.length, DL.sizeof('P'), LIBC::COMPARE)
p ptr.to_a('S', ary.length)
tv = LIBC::Timeval.malloc
tz = LIBC::Timezone.malloc
LIBC.gettimeofday(tv, tz)
p Time.at(tv.tv_sec)

View file

@ -1,19 +0,0 @@
# This script works on Windows.
require 'dl'
User32 = DL.dlopen("user32")
Kernel32 = DL.dlopen("kernel32")
MB_OK = 0
MB_OKCANCEL = 1
message_box = User32['MessageBoxA', 'ILSSI']
r,rs = message_box.call(0, 'ok?', 'error', MB_OKCANCEL)
case r
when 1
print("OK!\n")
when 2
print("Cancel!\n")
end

View file

@ -1,18 +0,0 @@
# This script works on Windows.
require 'dl/win32'
MB_OK = 0
MB_OKCANCEL = 1
message_box = Win32API.new("user32",'MessageBoxA', 'ISSI', 'I')
r = message_box.call(0, 'ok?', 'error', MB_OKCANCEL)
case r
when 1
print("OK!\n")
when 2
print("Cancel!\n")
else
p r
end

View file

@ -1,87 +0,0 @@
# -*- ruby -*-
# Display a file name and stream names of a file with those size.
require 'dl'
require 'dl/import'
module NTFS
extend DL::Importable
dlload "kernel32.dll"
OPEN_EXISTING = 3
GENERIC_READ = 0x80000000
BACKUP_DATA = 0x00000001
BACKUP_ALTERNATE_DATA = 0x00000004
FILE_SHARE_READ = 0x00000001
FILE_FLAG_BACKUP_SEMANTICS = 0x02000000
typealias "LPSECURITY_ATTRIBUTES", "void*"
extern "BOOL BackupRead(HANDLE, PBYTE, DWORD, PDWORD, BOOL, BOOL, PVOID)"
extern "BOOL BackupSeek(HANDLE, DWORD, DWORD, PDWORD, PDWORD, PVOID)"
extern "BOOL CloseHandle(HANDLE)"
extern "HANDLE CreateFile(LPCSTR, DWORD, DWORD, LPSECURITY_ATTRIBUTES,
DWORD, DWORD, HANDLE)"
module_function
def streams(filename)
status = []
h = createFile(filename,GENERIC_READ,FILE_SHARE_READ,nil,
OPEN_EXISTING,FILE_FLAG_BACKUP_SEMANTICS,0)
if( h != 0 )
begin
# allocate the memory for backup data used in backupRead().
data = DL.malloc(DL.sizeof("L5"))
data.struct!("LLLLL", :id, :attrs, :size_low, :size_high, :name_size)
# allocate memories for references to long values used in backupRead().
context = DL.malloc(DL.sizeof("L"))
lval = DL.malloc(DL.sizeof("L"))
while( backupRead(h, data, data.size, lval, false, false, context) )
size = data[:size_low] + (data[:size_high] << (DL.sizeof("I") * 8))
case data[:id]
when BACKUP_ALTERNATE_DATA
stream_name = DL.malloc(data[:name_size])
backupRead(h, stream_name, stream_name.size,
lval, false, false, context)
name = stream_name[0, stream_name.size]
name.tr!("\000","")
if( name =~ /^:(.*?):.*$/ )
status.push([$1,size])
end
when BACKUP_DATA
status.push([nil,size])
else
raise(RuntimeError, "unknown data type #{data[:id]}.")
end
l1 = DL.malloc(DL.sizeof("L"))
l2 = DL.malloc(DL.sizeof("L"))
if( !backupSeek(h, data[:size_low], data[:size_high], l1, l2, context) )
break
end
end
ensure
backupRead(h, nil, 0, lval, true, false, context)
closeHandle(h)
end
return status
else
raise(RuntimeError, "can't open #{filename}.\n")
end
end
end
ARGV.each{|filename|
if( File.exist?(filename) )
NTFS.streams(filename).each{|name,size|
if( name )
print("#{filename}:#{name}\t#{size}bytes\n")
else
print("#{filename}\t#{size}bytes\n")
end
}
end
}

View file

@ -1,991 +0,0 @@
/* -*- mode: C; c-file-style: "gnu" -*-
* $Id$
*/
#include <ruby.h>
#include <errno.h>
#include "dl.h"
VALUE rb_cDLSymbol;
static const char *
char2type(int ch)
{
switch (ch) {
case '0':
return "void";
case 'P':
return "void *";
case 'p':
return "void *";
case 'C':
return "char";
case 'c':
return "char *";
case 'H':
return "short";
case 'h':
return "short *";
case 'I':
return "int";
case 'i':
return "int *";
case 'L':
return "long";
case 'l':
return "long *";
case 'F':
return "double";
case 'f':
return "double *";
case 'D':
return "double";
case 'd':
return "double *";
case 'S':
return "const char *";
case 's':
return "char *";
case 'A':
return "[]";
case 'a':
return "[]"; /* ?? */
}
return NULL;
}
void
dlsym_free(struct sym_data *data)
{
if( data->name ){
DEBUG_CODE({
printf("dlsym_free(): free(data->name:%s)\n",data->name);
});
free(data->name);
}
if( data->type ){
DEBUG_CODE({
printf("dlsym_free(): free(data->type:%s)\n",data->type);
});
free(data->type);
}
}
VALUE
rb_dlsym_new(void (*func)(), const char *name, const char *type)
{
VALUE val;
struct sym_data *data;
const char *ptype;
rb_secure(4);
if( !type || !type[0] ){
return rb_dlptr_new((void*)func, 0, 0);
}
for( ptype = type; *ptype; ptype ++ ){
if( ! char2type(*ptype) ){
rb_raise(rb_eDLTypeError, "unknown type specifier '%c'", *ptype);
}
}
if( func ){
val = Data_Make_Struct(rb_cDLSymbol, struct sym_data, 0, dlsym_free, data);
data->func = func;
data->name = name ? strdup(name) : NULL;
data->type = type ? strdup(type) : NULL;
data->len = type ? strlen(type) : 0;
#if !(defined(DLSTACK))
if( data->len - 1 > MAX_ARG ){
rb_raise(rb_eDLError, "maximum number of arguments is %d.", MAX_ARG);
}
#endif
}
else{
val = Qnil;
}
return val;
}
freefunc_t
rb_dlsym2csym(VALUE val)
{
struct sym_data *data;
freefunc_t func;
if( rb_obj_is_kind_of(val, rb_cDLSymbol) ){
Data_Get_Struct(val, struct sym_data, data);
func = data->func;
}
else if( val == Qnil ){
func = NULL;
}
else{
rb_raise(rb_eTypeError, "DL::Symbol was expected");
}
return func;
}
VALUE
rb_dlsym_s_allocate(VALUE klass)
{
VALUE obj;
struct sym_data *data;
obj = Data_Make_Struct(klass, struct sym_data, 0, dlsym_free, data);
data->func = 0;
data->name = 0;
data->type = 0;
data->len = 0;
return obj;
}
VALUE
rb_dlsym_initialize(int argc, VALUE argv[], VALUE self)
{
VALUE addr, name, type;
struct sym_data *data;
void *saddr;
const char *sname, *stype;
rb_scan_args(argc, argv, "12", &addr, &name, &type);
saddr = (void*)(DLNUM2LONG(rb_Integer(addr)));
if (!NIL_P(name)) StringValue(name);
stype = NIL_P(type) ? NULL : StringValuePtr(type);
sname = NIL_P(name) ? NULL : RSTRING(name)->ptr;
if( saddr ){
Data_Get_Struct(self, struct sym_data, data);
if( data->name ) free(data->name);
if( data->type ) free(data->type);
data->func = saddr;
data->name = sname ? strdup(sname) : 0;
data->type = stype ? strdup(stype) : 0;
data->len = stype ? strlen(stype) : 0;
}
return Qnil;
}
VALUE
rb_s_dlsym_char2type(VALUE self, VALUE ch)
{
const char *type;
type = char2type(StringValuePtr(ch)[0]);
if (type == NULL)
return Qnil;
else
return rb_str_new2(type);
}
VALUE
rb_dlsym_name(VALUE self)
{
struct sym_data *sym;
Data_Get_Struct(self, struct sym_data, sym);
return sym->name ? rb_tainted_str_new2(sym->name) : Qnil;
}
VALUE
rb_dlsym_proto(VALUE self)
{
struct sym_data *sym;
Data_Get_Struct(self, struct sym_data, sym);
return sym->type ? rb_tainted_str_new2(sym->type) : Qnil;
}
VALUE
rb_dlsym_cproto(VALUE self)
{
struct sym_data *sym;
const char *ptype, *typestr;
size_t len;
VALUE val;
Data_Get_Struct(self, struct sym_data, sym);
ptype = sym->type;
if( ptype ){
typestr = char2type(*ptype++);
len = strlen(typestr);
val = rb_tainted_str_new(typestr, len);
if (typestr[len - 1] != '*')
rb_str_cat(val, " ", 1);
if( sym->name ){
rb_str_cat2(val, sym->name);
}
else{
rb_str_cat2(val, "(null)");
}
rb_str_cat(val, "(", 1);
while (*ptype) {
const char *ty = char2type(*ptype++);
rb_str_cat2(val, ty);
if (*ptype)
rb_str_cat(val, ", ", 2);
}
rb_str_cat(val, ");", 2);
}
else{
val = rb_tainted_str_new2("void (");
if( sym->name ){
rb_str_cat2(val, sym->name);
}
else{
rb_str_cat2(val, "(null)");
}
rb_str_cat2(val, ")()");
}
return val;
}
VALUE
rb_dlsym_inspect(VALUE self)
{
VALUE proto;
VALUE val;
char *str;
int str_size;
struct sym_data *sym;
Data_Get_Struct(self, struct sym_data, sym);
proto = rb_dlsym_cproto(self);
str_size = RSTRING(proto)->len + 100;
str = dlmalloc(str_size);
snprintf(str, str_size - 1,
"#<DL::Symbol:0x%p func=0x%p '%s'>",
sym, sym->func, RSTRING(proto)->ptr);
val = rb_tainted_str_new2(str);
dlfree(str);
return val;
}
static int
stack_size(struct sym_data *sym)
{
int i;
int size;
size = 0;
for( i=1; i < sym->len; i++ ){
switch(sym->type[i]){
case 'C':
case 'H':
case 'I':
case 'L':
size += sizeof(long);
break;
case 'F':
size += sizeof(float);
break;
case 'D':
size += sizeof(double);
break;
case 'c':
case 'h':
case 'i':
case 'l':
case 'f':
case 'd':
case 'p':
case 'P':
case 's':
case 'S':
case 'a':
case 'A':
size += sizeof(void*);
break;
default:
return -(sym->type[i]);
}
}
return size;
}
static ID rb_dl_id_DLErrno;
static VALUE
rb_dl_get_last_error(VALUE self)
{
return rb_thread_local_aref(rb_thread_current(), rb_dl_id_DLErrno);
}
static VALUE
rb_dl_set_last_error(VALUE self, VALUE val)
{
errno = NUM2INT(val);
rb_thread_local_aset(rb_thread_current(), rb_dl_id_DLErrno, val);
return Qnil;
}
#ifdef HAVE_WINDOWS_H
#include <windows.h>
static ID rb_dl_id_DLW32Error;
static VALUE
rb_dl_win32_get_last_error(VALUE self)
{
return rb_thread_local_aref(rb_thread_current(), rb_dl_id_DLW32Error);
}
static VALUE
rb_dl_win32_set_last_error(VALUE self, VALUE val)
{
SetLastError(NUM2INT(val));
rb_thread_local_aset(rb_thread_current(), rb_dl_id_DLW32Error, val);
return Qnil;
}
#endif
#ifdef DLSTACK_GUARD
# ifdef __MSVC_RUNTIME_CHECKS
# pragma runtime_checks("s", off)
# endif
# if _MSC_VER >= 1300
__declspec(noinline)
# endif
static int
rb_dlsym_guardcall(char type, ANY_TYPE *ret, long *stack, void *func)
{
char *volatile guard = ALLOCA_N(char, 1); /* guard stack pointer */
switch(type){
case '0':
{
void (*f)(DLSTACK_PROTO) = func;
f(DLSTACK_ARGS);
}
break;
case 'P':
case 'p':
{
void * (*f)(DLSTACK_PROTO) = func;
ret->p = f(DLSTACK_ARGS);
}
break;
case 'C':
case 'c':
{
char (*f)(DLSTACK_PROTO) = func;
ret->c = f(DLSTACK_ARGS);
}
break;
case 'H':
case 'h':
{
short (*f)(DLSTACK_PROTO) = func;
ret->h = f(DLSTACK_ARGS);
}
break;
case 'I':
case 'i':
{
int (*f)(DLSTACK_PROTO) = func;
ret->i = f(DLSTACK_ARGS);
}
break;
case 'L':
case 'l':
{
long (*f)(DLSTACK_PROTO) = func;
ret->l = f(DLSTACK_ARGS);
}
break;
case 'F':
case 'f':
{
float (*f)(DLSTACK_PROTO) = func;
ret->f = f(DLSTACK_ARGS);
}
break;
case 'D':
case 'd':
{
double (*f)(DLSTACK_PROTO) = func;
ret->d = f(DLSTACK_ARGS);
}
break;
case 'S':
case 's':
{
char * (*f)(DLSTACK_PROTO) = func;
ret->s = f(DLSTACK_ARGS);
}
break;
default:
return 0;
}
return 1;
}
# ifdef __MSVC_RUNTIME_CHECKS
# pragma runtime_checks("s", restore)
# endif
#endif /* defined(DLSTACK_GUARD) */
VALUE
rb_dlsym_call(int argc, VALUE argv[], VALUE self)
{
struct sym_data *sym;
ANY_TYPE *args;
ANY_TYPE *dargs;
ANY_TYPE ret;
int *dtypes;
VALUE val;
VALUE dvals;
int i;
long ftype;
void *func;
rb_secure_update(self);
Data_Get_Struct(self, struct sym_data, sym);
DEBUG_CODE({
printf("rb_dlsym_call(): type = '%s', func = 0x%x\n", sym->type, sym->func);
});
if( (sym->len - 1) != argc ){
rb_raise(rb_eArgError, "%d arguments are needed", sym->len - 1);
}
ftype = 0;
dvals = Qnil;
args = ALLOC_N(ANY_TYPE, sym->len - 1);
dargs = ALLOC_N(ANY_TYPE, sym->len - 1);
dtypes = ALLOC_N(int, sym->len - 1);
#define FREE_ARGS {xfree(args); xfree(dargs); xfree(dtypes);}
for( i = sym->len - 2; i >= 0; i-- ){
dtypes[i] = 0;
switch( sym->type[i+1] ){
case 'p':
dtypes[i] = 'p';
case 'P':
{
struct ptr_data *data;
VALUE pval;
if( argv[i] == Qnil ){
ANY2P(args[i]) = DLVOIDP(0);
}
else{
if( rb_obj_is_kind_of(argv[i], rb_cDLPtrData) ){
pval = argv[i];
}
else{
pval = rb_funcall(argv[i], rb_intern("to_ptr"), 0);
if( !rb_obj_is_kind_of(pval, rb_cDLPtrData) ){
rb_raise(rb_eDLTypeError, "unexpected type of argument #%d", i);
}
}
Data_Get_Struct(pval, struct ptr_data, data);
ANY2P(args[i]) = DLVOIDP(data->ptr);
}
}
PUSH_P(ftype);
break;
case 'a':
dtypes[i] = 'a';
case 'A':
if( argv[i] == Qnil ){
ANY2P(args[i]) = DLVOIDP(0);
}
else{
ANY2P(args[i]) = DLVOIDP(rb_ary2cary(0, argv[i], NULL));
}
PUSH_P(ftype);
break;
case 'C':
ANY2C(args[i]) = DLCHAR(NUM2CHR(argv[i]));
PUSH_C(ftype);
break;
case 'c':
ANY2C(dargs[i]) = DLCHAR(NUM2CHR(argv[i]));
ANY2P(args[i]) = DLVOIDP(&(ANY2C(dargs[i])));
dtypes[i] = 'c';
PUSH_P(ftype);
break;
case 'H':
ANY2H(args[i]) = DLSHORT(NUM2INT(argv[i]));
PUSH_C(ftype);
break;
case 'h':
ANY2H(dargs[i]) = DLSHORT(NUM2INT(argv[i]));
ANY2P(args[i]) = DLVOIDP(&(ANY2H(dargs[i])));
dtypes[i] = 'h';
PUSH_P(ftype);
break;
case 'I':
ANY2I(args[i]) = DLINT(NUM2INT(argv[i]));
PUSH_I(ftype);
break;
case 'i':
ANY2I(dargs[i]) = DLINT(NUM2INT(argv[i]));
ANY2P(args[i]) = DLVOIDP(&(ANY2I(dargs[i])));
dtypes[i] = 'i';
PUSH_P(ftype);
break;
case 'L':
ANY2L(args[i]) = DLNUM2LONG(argv[i]);
PUSH_L(ftype);
break;
case 'l':
ANY2L(dargs[i]) = DLNUM2LONG(argv[i]);
ANY2P(args[i]) = DLVOIDP(&(ANY2L(dargs[i])));
dtypes[i] = 'l';
PUSH_P(ftype);
break;
case 'F':
Check_Type(argv[i], T_FLOAT);
ANY2F(args[i]) = DLFLOAT(RFLOAT(argv[i])->value);
PUSH_F(ftype);
break;
case 'f':
Check_Type(argv[i], T_FLOAT);
ANY2F(dargs[i]) = DLFLOAT(RFLOAT(argv[i])->value);
ANY2P(args[i]) = DLVOIDP(&(ANY2F(dargs[i])));
dtypes[i] = 'f';
PUSH_P(ftype);
break;
case 'D':
Check_Type(argv[i], T_FLOAT);
ANY2D(args[i]) = RFLOAT(argv[i])->value;
PUSH_D(ftype);
break;
case 'd':
Check_Type(argv[i], T_FLOAT);
ANY2D(dargs[i]) = RFLOAT(argv[i])->value;
ANY2P(args[i]) = DLVOIDP(&(ANY2D(dargs[i])));
dtypes[i] = 'd';
PUSH_P(ftype);
break;
case 'S':
if( argv[i] == Qnil ){
ANY2S(args[i]) = DLSTR(0);
}
else{
VALUE str = argv[i];
SafeStringValue(str);
ANY2S(args[i]) = DLSTR(RSTRING(str)->ptr);
}
PUSH_P(ftype);
break;
case 's':
{
VALUE str = argv[i];
SafeStringValue(str);
ANY2S(args[i]) = DLSTR(dlmalloc(RSTRING(str)->len + 1));
memcpy((char*)(ANY2S(args[i])), RSTRING(str)->ptr, RSTRING(str)->len + 1);
dtypes[i] = 's';
}
PUSH_P(ftype);
break;
default:
FREE_ARGS;
rb_raise(rb_eDLTypeError,
"unknown type '%c' of the return value.",
sym->type[i+1]);
}
}
switch( sym->type[0] ){
case '0':
PUSH_0(ftype);
break;
case 'P':
case 'p':
case 'S':
case 's':
case 'A':
case 'a':
PUSH_P(ftype);
break;
case 'C':
case 'c':
PUSH_C(ftype);
break;
case 'H':
case 'h':
PUSH_H(ftype);
break;
case 'I':
case 'i':
PUSH_I(ftype);
break;
case 'L':
case 'l':
PUSH_L(ftype);
break;
case 'F':
case 'f':
PUSH_F(ftype);
break;
case 'D':
case 'd':
PUSH_D(ftype);
break;
default:
FREE_ARGS;
rb_raise(rb_eDLTypeError,
"unknown type `%c' of the return value.",
sym->type[0]);
}
func = sym->func;
#if defined(DLSTACK)
{
#if defined(DLSTACK_SIZE)
int stk_size;
long stack[DLSTACK_SIZE];
long *sp;
sp = stack;
stk_size = stack_size(sym);
if( stk_size < 0 ){
FREE_ARGS;
rb_raise(rb_eDLTypeError, "unknown type '%c'.", -stk_size);
}
else if( stk_size > (int)(DLSTACK_SIZE) ){
FREE_ARGS;
rb_raise(rb_eArgError, "too many arguments.");
}
#endif
DLSTACK_START(sym);
#if defined(DLSTACK_REVERSE)
for( i = sym->len - 2; i >= 0; i-- )
#else
for( i = 0; i <= sym->len -2; i++ )
#endif
{
switch( sym->type[i+1] ){
case 'p':
case 'P':
DLSTACK_PUSH_P(ANY2P(args[i]));
break;
case 'a':
case 'A':
DLSTACK_PUSH_P(ANY2P(args[i]));
break;
case 'C':
DLSTACK_PUSH_C(ANY2C(args[i]));
break;
case 'c':
DLSTACK_PUSH_P(ANY2P(args[i]));
break;
case 'H':
DLSTACK_PUSH_H(ANY2H(args[i]));
break;
case 'h':
DLSTACK_PUSH_P(ANY2P(args[i]));
break;
case 'I':
DLSTACK_PUSH_I(ANY2I(args[i]));
break;
case 'i':
DLSTACK_PUSH_P(ANY2P(args[i]));
break;
case 'L':
DLSTACK_PUSH_L(ANY2L(args[i]));
break;
case 'l':
DLSTACK_PUSH_P(ANY2P(args[i]));
break;
case 'F':
DLSTACK_PUSH_F(ANY2F(args[i]));
break;
case 'f':
DLSTACK_PUSH_P(ANY2P(args[i]));
break;
case 'D':
DLSTACK_PUSH_D(ANY2D(args[i]));
break;
case 'd':
DLSTACK_PUSH_P(ANY2P(args[i]));
break;
case 'S':
case 's':
DLSTACK_PUSH_P(ANY2S(args[i]));
break;
}
}
DLSTACK_END(sym->type);
#ifdef DLSTACK_GUARD
if(!rb_dlsym_guardcall(sym->type[0], &ret, stack, func)) {
FREE_ARGS;
rb_raise(rb_eDLTypeError, "unknown type `%c'", sym->type[0]);
}
#else /* defined(DLSTACK_GUARD) */
{
switch( sym->type[0] ){
case '0':
{
void (*f)(DLSTACK_PROTO) = func;
f(DLSTACK_ARGS);
}
break;
case 'P':
case 'p':
{
void * (*f)(DLSTACK_PROTO) = func;
ret.p = f(DLSTACK_ARGS);
}
break;
case 'C':
case 'c':
{
char (*f)(DLSTACK_PROTO) = func;
ret.c = f(DLSTACK_ARGS);
}
break;
case 'H':
case 'h':
{
short (*f)(DLSTACK_PROTO) = func;
ret.h = f(DLSTACK_ARGS);
}
break;
case 'I':
case 'i':
{
int (*f)(DLSTACK_PROTO) = func;
ret.i = f(DLSTACK_ARGS);
}
break;
case 'L':
case 'l':
{
long (*f)(DLSTACK_PROTO) = func;
ret.l = f(DLSTACK_ARGS);
}
break;
case 'F':
case 'f':
{
float (*f)(DLSTACK_PROTO) = func;
ret.f = f(DLSTACK_ARGS);
}
break;
case 'D':
case 'd':
{
double (*f)(DLSTACK_PROTO) = func;
ret.d = f(DLSTACK_ARGS);
}
break;
case 'S':
case 's':
{
char * (*f)(DLSTACK_PROTO) = func;
ret.s = f(DLSTACK_ARGS);
}
break;
default:
FREE_ARGS;
rb_raise(rb_eDLTypeError, "unknown type `%c'", sym->type[0]);
}
}
#endif /* defubed(DLSTACK_GUARD) */
{
/*
* We should get the value of errno/GetLastError() before calling another functions.
*/
int last_errno = errno;
#ifdef _WIN32
DWORD win32_last_err = GetLastError();
#endif
rb_thread_local_aset(rb_thread_current(), rb_dl_id_DLErrno, INT2NUM(last_errno));
#ifdef _WIN32
rb_thread_local_aset(rb_thread_current(), rb_dl_id_DLW32Error, INT2NUM(win32_last_err));
#endif
}
}
#else /* defined(DLSTACK) */
switch(ftype){
#include "call.func"
default:
FREE_ARGS;
rb_raise(rb_eDLTypeError, "unsupported function type `%s'", sym->type);
}
#endif /* defined(DLSTACK) */
switch( sym->type[0] ){
case '0':
val = Qnil;
break;
case 'P':
val = rb_dlptr_new((void*)(ANY2P(ret)), 0, 0);
break;
case 'p':
val = rb_dlptr_new((void*)(ANY2P(ret)), 0, dlfree);
break;
case 'C':
case 'c':
val = CHR2FIX((char)(ANY2C(ret)));
break;
case 'H':
case 'h':
val = INT2NUM((short)(ANY2H(ret)));
break;
case 'I':
case 'i':
val = INT2NUM((int)(ANY2I(ret)));
break;
case 'L':
case 'l':
val = DLLONG2NUM((long)(ANY2L(ret)));
break;
case 'F':
case 'f':
val = rb_float_new((double)(ANY2F(ret)));
break;
case 'D':
case 'd':
val = rb_float_new((double)(ANY2D(ret)));
break;
case 'S':
if( ANY2S(ret) ){
val = rb_tainted_str_new2((char*)(ANY2S(ret)));
}
else{
val = Qnil;
}
break;
case 's':
if( ANY2S(ret) ){
val = rb_tainted_str_new2((char*)(ANY2S(ret)));
DEBUG_CODE({
printf("dlfree(%s)\n",(char*)(ANY2S(ret)));
});
dlfree((void*)(ANY2S(ret)));
}
else{
val = Qnil;
}
break;
default:
FREE_ARGS;
rb_raise(rb_eDLTypeError, "unknown type `%c'", sym->type[0]);
}
dvals = rb_ary_new();
for( i = 0; i <= sym->len - 2; i++ ){
if( dtypes[i] ){
switch( dtypes[i] ){
case 'c':
rb_ary_push(dvals, CHR2FIX(*((char*)(ANY2P(args[i])))));
break;
case 'h':
rb_ary_push(dvals, INT2NUM(*((short*)(ANY2P(args[i])))));
break;
case 'i':
rb_ary_push(dvals, INT2NUM(*((int*)(ANY2P(args[i])))));
break;
case 'l':
rb_ary_push(dvals, DLLONG2NUM(*((long*)(ANY2P(args[i])))));
break;
case 'f':
rb_ary_push(dvals, rb_float_new(*((float*)(ANY2P(args[i])))));
break;
case 'd':
rb_ary_push(dvals, rb_float_new(*((double*)(ANY2P(args[i])))));
break;
case 'p':
rb_ary_push(dvals, rb_dlptr_new((void*)(ANY2P(args[i])), 0, 0));
break;
case 'a':
rb_ary_push(dvals, rb_dlptr_new((void*)ANY2P(args[i]), 0, 0));
break;
case 's':
rb_ary_push(dvals, rb_tainted_str_new2((char*)ANY2S(args[i])));
DEBUG_CODE({
printf("dlfree(%s)\n",(char*)ANY2S(args[i]));
});
dlfree((void*)ANY2S(args[i]));
break;
default:
{
char c = dtypes[i];
FREE_ARGS;
rb_raise(rb_eRuntimeError, "unknown argument type '%c'", i, c);
}
}
}
else{
switch( sym->type[i+1] ){
case 'A':
dlfree((void*)ANY2P(args[i]));
break;
}
rb_ary_push(dvals, argv[i]);
}
}
#undef FREE_ARGS
return rb_assoc_new(val,dvals);
}
VALUE
rb_dlsym_to_i(VALUE self)
{
struct sym_data *sym;
Data_Get_Struct(self, struct sym_data, sym);
return DLLONG2NUM(sym);
}
VALUE
rb_dlsym_to_ptr(VALUE self)
{
struct sym_data *sym;
Data_Get_Struct(self, struct sym_data, sym);
return rb_dlptr_new(sym->func, sizeof(freefunc_t), 0);
}
void
Init_dlsym()
{
rb_cDLSymbol = rb_define_class_under(rb_mDL, "Symbol", rb_cObject);
rb_define_alloc_func(rb_cDLSymbol, rb_dlsym_s_allocate);
rb_define_singleton_method(rb_cDLSymbol, "char2type", rb_s_dlsym_char2type, 1);
rb_define_method(rb_cDLSymbol, "initialize", rb_dlsym_initialize, -1);
rb_define_method(rb_cDLSymbol, "call", rb_dlsym_call, -1);
rb_define_method(rb_cDLSymbol, "[]", rb_dlsym_call, -1);
rb_define_method(rb_cDLSymbol, "name", rb_dlsym_name, 0);
rb_define_method(rb_cDLSymbol, "proto", rb_dlsym_proto, 0);
rb_define_method(rb_cDLSymbol, "cproto", rb_dlsym_cproto, 0);
rb_define_method(rb_cDLSymbol, "inspect", rb_dlsym_inspect, 0);
rb_define_method(rb_cDLSymbol, "to_s", rb_dlsym_cproto, 0);
rb_define_method(rb_cDLSymbol, "to_ptr", rb_dlsym_to_ptr, 0);
rb_define_method(rb_cDLSymbol, "to_i", rb_dlsym_to_i, 0);
rb_dl_id_DLErrno = rb_intern("DLErrno");
rb_define_singleton_method(rb_mDL, "last_error", rb_dl_get_last_error, 0);
rb_define_singleton_method(rb_mDL, "last_error=", rb_dl_set_last_error, 1);
#ifdef _WIN32
rb_dl_id_DLW32Error = rb_intern("DLW32Error");
rb_define_singleton_method(rb_mDL, "win32_last_error", rb_dl_win32_get_last_error, 0);
rb_define_singleton_method(rb_mDL, "win32_last_error=", rb_dl_win32_set_last_error, 1);
#endif
}

View file

@ -1,28 +0,0 @@
EXPORTS
test_alloc_test_struct
test_append
test_arylen
test_c2i
test_call_func1
test_callback1
test_close
test_d2f
test_f2d
test_fill_test_struct
test_fill_test_union
test_gets
test_i2c
test_init
test_isucc
test_lcc
test_lsucc
test_open
test_strcat
test_strlen
test_succ
test_data_init
test_data_add
test_data_aref
test_set_long_value
test_get_long_value
internal_long_value

View file

@ -1,247 +0,0 @@
#include <stdio.h>
#include <string.h>
static char internal_string[] = "internal_string";
long internal_long_value = 100;
struct test_struct {
char c;
long l;
};
union test_union {
char c;
int i;
long l;
void *p;
};
struct test_data {
char name[1024];
struct test_data *next;
};
long
test_get_long_value()
{
return internal_long_value;
};
void
test_set_long_value(long l)
{
internal_long_value = l;
};
void
test_fill_test_struct(struct test_struct *ptr, char c, long l)
{
ptr->c = c;
ptr->l = l;
};
void
test_fill_test_union(union test_union *ptr, long l)
{
ptr->l = l;
};
struct test_struct *
test_alloc_test_struct(char c, long l)
{
struct test_struct *data;
data = (struct test_struct *)malloc(sizeof(struct test_struct));
data->c = c;
data->l = l;
return data;
};
int
test_c2i(char c)
{
return (int)c;
};
char
test_i2c(int i)
{
return (char)i;
};
long
test_lcc(char c1, char c2)
{
return (long)(c1 + c2);
};
double
test_f2d(float f)
{
double d;
d = f;
return d;
};
float
test_d2f(double d)
{
float f;
f = d;
return f;
};
int
test_strlen(const char *str)
{
return strlen(str);
};
int
test_isucc(int i)
{
return (i+1);
};
long
test_lsucc(long l)
{
return (l+1);
};
void
test_succ(long *l)
{
(*l)++;
};
char *
test_strcat(char *str1, const char *str2)
{
return strcat(str1, str2);
};
int
test_arylen(char *ary[])
{
int i;
for( i=0; ary[i]; i++ ){};
return i;
};
void
test_append(char *ary[], int len, char *astr)
{
int i;
int size1,size2;
char *str;
size2 = strlen(astr);
for( i=0; i <= len - 1; i++ ){
size1 = strlen(ary[i]);
str = (char*)malloc(size1 + size2 + 1);
strcpy(str, ary[i]);
strcat(str, astr);
ary[i] = str;
};
};
int
test_init(int *argc, char **argv[])
{
int i;
char s[256];
for( i=0; i < (*argc); i++ ){
sprintf(s, "arg%d", i);
if( strcmp((*argv)[i], s) != 0 ){
return 1;
}
}
return 0;
}
FILE *
test_open(const char *filename, const char *mode)
{
FILE *file;
file = fopen(filename,mode);
return file;
};
void
test_close(FILE *file)
{
fclose(file);
};
char *
test_gets(char *s, int size, FILE *f)
{
return fgets(s,size,f);
};
typedef int callback1_t(int, char *);
#define CALLBACK_MSG "callback message"
int
test_callback1(int err, const char *msg)
{
if( strcmp(msg, CALLBACK_MSG) == 0 ){
return 1;
}
else{
return 0;
}
}
int
test_call_func1(callback1_t *func)
{
if( func ){
return (*func)(0, CALLBACK_MSG);
}
else{
return 0;
}
}
struct test_data *
test_data_init()
{
struct test_data *data;
data = (struct test_data *)malloc(sizeof(struct test_data));
data->next = NULL;
memset(data->name, 0, 1024);
return data;
};
void
test_data_add(struct test_data *list, const char *name)
{
struct test_data *data;
data = (struct test_data *)malloc(sizeof(struct test_data));
memset(data->name, 0, 1024);
strncpy(data->name, name, 1024);
data->next = list->next;
list->next = data;
};
struct test_data *
test_data_aref(struct test_data *list, int i)
{
struct test_data *data;
int j;
for( data = list->next, j=0; data; data = data->next, j++ ){
if( i == j ){
return data;
};
};
return NULL;
};

View file

@ -1,295 +0,0 @@
# -*- ruby -*-
require 'dl'
require 'dl/import'
$FAIL = 0
$TOTAL = 0
def assert(label, ty, *conds)
$TOTAL += 1
cond = !conds.include?(false)
if( cond )
printf("succeed in `#{label}'\n")
else
$FAIL += 1
case ty
when :may
printf("fail in `#{label}' ... expected\n")
when :must
printf("fail in `#{label}' ... unexpected\n")
when :raise
raise(RuntimeError, "fail in `#{label}'")
end
end
end
def debug(*xs)
if( $DEBUG )
xs.each{|x|
p x
}
end
end
print("DLSTACK = #{DL::DLSTACK}\n")
print("MAX_ARG = #{DL::MAX_ARG}\n")
print("\n")
print("DL::FREE = #{DL::FREE.inspect}\n")
print("\n")
$LIB = nil
if( !$LIB && File.exist?("libtest.so") )
$LIB = "./libtest.so"
end
if( !$LIB && File.exist?("test/libtest.so") )
$LIB = "./test/libtest.so"
end
module LIBTest
extend DL::Importable
dlload($LIB)
extern "int test_c2i(char)"
extern "char test_i2c(int)"
extern "long test_lcc(char, char)"
extern "double test_f2d(float)"
extern "float test_d2f(double)"
extern "int test_strlen(char*)"
extern "int test_isucc(int)"
extern "long test_lsucc(long)"
extern "void test_succ(long *)"
extern "int test_arylen(int [])"
extern "void test_append(char*[], int, char *)"
end
DL.dlopen($LIB){|h|
c2i = h["test_c2i","IC"]
debug c2i
r,rs = c2i[?a]
debug r,rs
assert("c2i", :may, r == ?a)
assert("extern c2i", :must, r == LIBTest.test_c2i(?a))
i2c = h["test_i2c","CI"]
debug i2c
r,rs = i2c[?a]
debug r,rs
assert("i2c", :may, r == ?a)
assert("exern i2c", :must, r == LIBTest.test_i2c(?a))
lcc = h["test_lcc","LCC"]
debug lcc
r,rs = lcc[1,2]
assert("lcc", :may, r == 3)
assert("extern lcc", :must, r == LIBTest.test_lcc(1,2))
f2d = h["test_f2d","DF"]
debug f2d
r,rs = f2d[20.001]
debug r,rs
assert("f2d", :may, r.to_i == 20)
assert("extern f2d", :must, r = LIBTest.test_f2d(20.001))
d2f = h["test_d2f","FD"]
debug d2f
r,rs = d2f[20.001]
debug r,rs
assert("d2f", :may, r.to_i == 20)
assert("extern d2f", :must, r == LIBTest.test_d2f(20.001))
strlen = h["test_strlen","IS"]
debug strlen
r,rs = strlen["0123456789"]
debug r,rs
assert("strlen", :must, r == 10)
assert("extern strlen", :must, r == LIBTest.test_strlen("0123456789"))
isucc = h["test_isucc","II"]
debug isucc
r,rs = isucc[2]
debug r,rs
assert("isucc", :must, r == 3)
assert("extern isucc", :must, r == LIBTest.test_isucc(2))
lsucc = h["test_lsucc","LL"]
debug lsucc
r,rs = lsucc[10000000]
debug r,rs
assert("lsucc", :must, r == 10000001)
assert("extern lsucc", :must, r == LIBTest.test_lsucc(10000000))
succ = h["test_succ","0l"]
debug succ
r,rs = succ[0]
debug r,rs
assert("succ", :must, rs[0] == 1)
l = DL.malloc(DL.sizeof("L"))
l.struct!("L",:lval)
LIBTest.test_succ(l)
assert("extern succ", :must, rs[0] == l[:lval])
arylen = h["test_arylen","IA"]
debug arylen
r,rs = arylen[["a","b","c","d",nil]]
debug r,rs
assert("arylen", :must, r == 4)
arylen = h["test_arylen","IP"]
debug arylen
r,rs = arylen[["a","b","c","d",nil]]
debug r,rs
assert("arylen", :must, r == 4)
assert("extern arylen", :must, r == LIBTest.test_arylen(["a","b","c","d",nil]))
append = h["test_append","0aIS"]
debug append
r,rs = append[["a","b","c"],3,"x"]
debug r,rs
assert("append", :must, rs[0].to_a('S',3) == ["ax","bx","cx"])
LIBTest.test_append(["a","b","c"],3,"x")
assert("extern append", :must, rs[0].to_a('S',3) == LIBTest._args_[0].to_a('S',3))
strcat = h["test_strcat","SsS"]
debug strcat
r,rs = strcat["abc\0","x"]
debug r,rs
assert("strcat", :must, rs[0].to_s == "abcx")
init = h["test_init","IiP"]
debug init
argc = 3
argv = ["arg0","arg1","arg2"].to_ptr
r,rs = init[argc, argv.ref]
assert("init", :must, r == 0)
}
h = DL.dlopen($LIB)
sym_open = h["test_open", "PSS"]
sym_gets = h["test_gets", "SsIP"]
sym_close = h["test_close", "0P"]
debug sym_open,sym_gets,sym_close
line = "Hello world!\n"
File.open("tmp.txt", "w"){|f|
f.print(line)
}
fp,rs = sym_open["tmp.txt", "r"]
if( fp )
fp.free = sym_close
r,rs = sym_gets[" " * 256, 256, fp]
debug r,rs
assert("open,gets", :must, rs[0] == line)
ObjectSpace.define_finalizer(fp) {File.unlink("tmp.txt")}
fp = nil
else
assert("open,gets", :must, line == nil)
File.unlink("tmp.txt")
end
callback1 = h["test_callback1"]
debug callback1
r,rs = h["test_call_func1", "IP"][callback1]
debug r,rs
assert("callback1", :must, r == 1)
callback2 = DL.callback("LLP"){|num,ptr|
msg = ptr.to_s
if( msg == "callback message" )
2
else
0
end
}
debug callback2
r,rs = h["test_call_func1", "IP"][callback2]
debug r,rs
assert("callback2", :must, r == 2)
DL.remove_callback(callback2)
ptr = DL.malloc(DL.sizeof('CL'))
ptr.struct!("CL", :c, :l)
ptr["c"] = 0
ptr["l"] = 0
r,rs = h["test_fill_test_struct","0PIL"][ptr,100,1000]
debug r,rs
assert("fill_test_struct", :must, ptr["c"] == 100, ptr["l"] == 1000)
assert("fill_test_struct", :must, ptr[:c] == 100, ptr[:l] == 1000) unless (Fixnum === :-)
r,rs = h["test_alloc_test_struct", "PIL"][100,200]
r.free = DL::FREE
r.struct!("CL", :c, :l)
assert("alloc_test_struct", :must, r["c"] == 100, r["l"] == 200)
assert("alloc_test_struct", :must, r[:c] == 100, r[:l] == 200) unless (Fixnum === :-)
ptr = h["test_strlen"]
sym1 = DL::Symbol.new(ptr,"foo","0")
sym2 = h["test_strlen","LS"]
assert("Symbol.new", :must, ptr == sym1.to_ptr, sym1.to_ptr == sym2.to_ptr)
set_val = h["test_set_long_value","0"]
get_val = h["test_get_long_value","L"]
lval = get_val[][0]
ptr = h["internal_long_value"]
ptr.struct!("L", :l)
assert("get value", :must, ptr["l"] == lval)
assert("get value", :must, ptr[:l] == lval) unless (Fixnum === :-)
ptr["l"] = 200
lval = get_val[][0]
assert("set value", :must, ptr["l"] == lval)
assert("set value", :must, ptr[:l] == lval) unless (Fixnum === :-)
data_init = h["test_data_init", "P"]
data_add = h["test_data_add", "0PS"]
data_aref = h["test_data_aref", "PPI"]
r,rs = data_init[]
ptr = r
data_add[ptr, "name1"]
data_add[ptr, "name2"]
data_add[ptr, "name3"]
r,rs = data_aref[ptr, 1]
ptr = r
ptr.struct!("C1024P", :name, :next)
assert("data_aref", :must,
ptr["name"].collect{|c| c.chr}.join.split("\0")[0] == "name2")
assert("data_aref", :must,
ptr["name"].collect{|c| c.chr}.join.split("\0")[0] == "name2") unless (Fixnum === :-)
ptr = ptr["next"]
ptr.struct!("C1024P", :name, :next)
assert("data_aref", :must,
ptr["name"].collect{|c| c.chr}.join.split("\0")[0] == "name1")
assert("data_aref", :must,
ptr["name"].collect{|c| c.chr}.join.split("\0")[0] == "name1") unless (Fixnum === :-)
GC.start
ptr = DL::malloc(1024)
ptr.struct!("CHIL", "c", "h", "i", "l")
ptr["c"] = 1
ptr["h"] = 2
ptr["i"] = 3
ptr["l"] = 4
assert("struct!", :must,
ptr["c"] == 1 &&
ptr["h"] == 2 &&
ptr["i"] == 3 &&
ptr["l"] == 4)
ptr = DL::malloc(DL::sizeof("IP"))
ptr.struct!("IP", "n", "ptr")
ptr["n"] = 10
ptr["ptr"] = nil
assert("struct!", :must, ptr["n"] == 10 && ptr["ptr"] == nil)
GC.start
printf("fail/total = #{$FAIL}/#{$TOTAL}\n")

View file

@ -1,115 +0,0 @@
# example:
# DLTYPE[INT][:rb2c]["arg0"] => "NUM2INT(arg0)"
# DLTYPE[DOUBLE][:c2rb]["r"] => "rb_float_new(r)"
DLTYPE = {
VOID = 0x00 => {
:name => 'VOID',
:rb2c => nil,
:c2rb => nil,
:ctype => "void",
:stmem => "v",
:sym => true,
:cb => true,
},
CHAR = 0x01 => {
:name => 'CHAR',
:rb2c => proc{|x| "NUM2CHR(#{x})"},
:c2rb => proc{|x| "CHR2FIX(#{x})"},
:ctype => "char",
:stmem => "c",
:sym => false,
:cb => false,
},
SHORT = 0x02 => {
:name => 'SHORT',
:rb2c => proc{|x| "FIX2INT(#{x})"},
:c2rb => proc{|x| "INT2FIX(#{x})"},
:ctype => "short",
:stmem => "h",
:sym => false,
:cb => false,
},
INT = 0x03 => {
:name => 'INT',
:rb2c => proc{|x| "NUM2INT(#{x})"},
:c2rb => proc{|x| "INT2NUM(#{x})"},
:ctype => "int",
:stmem => "i",
:sym => true,
:cb => false,
},
LONG = 0x04 => {
:name => 'LONG',
:rb2c => proc{|x| "NUM2INT(#{x})"},
:c2rb => proc{|x| "INT2NUM(#{x})"},
:ctype => "long",
:stmem => "l",
:sym => true,
:cb => true,
},
FLOAT = 0x05 => {
:name => 'FLOAT',
:rb2c => proc{|x| "(float)(RFLOAT(#{x})->value)"},
:c2rb => proc{|x| "rb_float_new((double)#{x})"},
:ctype => "float",
:stmem => "f",
:sym => false,
:cb => false,
},
DOUBLE = 0x06 => {
:name => 'DOUBLE',
:rb2c => proc{|x| "RFLOAT(#{x})->value"},
:c2rb => proc{|x| "rb_float_new(#{x})"},
:ctype => "double",
:stmem => "d",
:sym => true,
:cb => true,
},
VOIDP = 0x07 => {
:name => 'VOIDP',
:rb2c => proc{|x| "rb_dlptr2cptr(#{x})"},
:c2rb => proc{|x| "rb_dlptr_new(#{x},sizeof(void*),0)"},
:ctype => "void *",
:stmem => "p",
:sym => true,
:cb => true,
},
}
def tpush(t, x)
(t << 3)|x
end
def tget(t, i)
(t & (0x07 << (i * 3))) >> (i * 3)
end
def types2num(types)
res = 0x00
r = types.reverse
r.each{|t|
res = tpush(res,t)
}
res
end
def num2types(num)
ts = []
i = 0
t = tget(num,i)
while( (t != VOID && i > 0) || (i == 0) )
ts.push(DLTYPE[t][:ctype])
i += 1
t = tget(num,i)
end
ts
end
def types2ctypes(types)
res = []
types.each{|t|
res.push(DLTYPE[t][:ctype])
}
res
end