ext/dl/sym.c


DEFINITIONS

This source file includes following functions.
  1. char2type
  2. dlsym_free
  3. rb_dlsym_new
  4. rb_dlsym2csym
  5. rb_dlsym_s_allocate
  6. rb_dlsym_initialize
  7. rb_s_dlsym_char2type
  8. rb_dlsym_name
  9. rb_dlsym_proto
  10. rb_dlsym_cproto
  11. rb_dlsym_inspect
  12. stack_size
  13. rb_dlsym_call
  14. rb_dlsym_to_i
  15. rb_dlsym_to_ptr
  16. Init_dlsym


   1  /* -*- C -*-
   2   * $Id: sym.c,v 1.13 2002/08/05 01:24:13 ttate Exp $
   3   */
   4  
   5  #include <ruby.h>
   6  #include "dl.h"
   7  
   8  VALUE rb_cDLSymbol;
   9  
  10  static const char *
  11  char2type(int ch)
  12  {
  13    switch (ch) {
  14    case '0':
  15      return "void";
  16    case 'P':
  17      return "void *";
  18    case 'p':
  19      return "void *";
  20    case 'C':
  21      return "char";
  22    case 'c':
  23      return "char *";
  24    case 'H':
  25      return "short";
  26    case 'h':
  27      return "short *";
  28    case 'I':
  29      return "int";
  30    case 'i':
  31      return "int *";
  32    case 'L':
  33      return "long";
  34    case 'l':
  35      return "long *";
  36    case 'F':
  37      return "double";
  38    case 'f':
  39      return "double *";
  40    case 'D':
  41      return "double";
  42    case 'd':
  43      return "double *";
  44    case 'S':
  45      return "const char *";
  46    case 's':
  47      return "char *";
  48    case 'A':
  49      return "[]";
  50    case 'a':
  51      return "[]"; /* ?? */
  52    };
  53    return NULL;
  54  }
  55  
  56  void
  57  dlsym_free(struct sym_data *data)
  58  {
  59    if( data->name ){
  60      DEBUG_CODE({
  61        printf("dlsym_free(): free(data->name:%s)\n",data->name);
  62      });
  63      free(data->name);
  64    };
  65    if( data->type ){
  66      DEBUG_CODE({
  67        printf("dlsym_free(): free(data->type:%s)\n",data->type);
  68      });
  69      free(data->type);
  70    };
  71  }
  72  
  73  VALUE
  74  rb_dlsym_new(void (*func)(), const char *name, const char *type)
  75  {
  76    VALUE val;
  77    struct sym_data *data;
  78    const char *ptype;
  79  
  80    if( !type || !type[0] ){
  81      return rb_dlptr_new((void*)func, 0, 0);
  82    };
  83  
  84    for( ptype = type; *ptype; ptype ++ ){
  85      if( ! char2type(*ptype) ){
  86        rb_raise(rb_eDLTypeError, "unknown type specifier '%c'", *ptype);
  87      };
  88    };
  89  
  90    if( func ){
  91      val = Data_Make_Struct(rb_cDLSymbol, struct sym_data, 0, dlsym_free, data);
  92      data->func = func;
  93      data->name = name ? strdup(name) : NULL;
  94      data->type = type ? strdup(type) : NULL;
  95      data->len  = type ? strlen(type) : 0;
  96  #if !(defined(DLSTACK))
  97      if( data->len - 1 > MAX_ARG ){
  98        rb_raise(rb_eDLError, "maximum number of arguments is %d.", MAX_ARG);
  99      };
 100  #endif
 101    }
 102    else{
 103      val = Qnil;
 104    };
 105  
 106    return val;
 107  }
 108  
 109  freefunc_t
 110  rb_dlsym2csym(VALUE val)
 111  {
 112    struct sym_data *data;
 113    freefunc_t func;
 114  
 115    if( rb_obj_is_kind_of(val, rb_cDLSymbol) ){
 116      Data_Get_Struct(val, struct sym_data, data);
 117      func = data->func;
 118    }
 119    else if( val == Qnil ){
 120      func = NULL;
 121    }
 122    else{
 123      rb_raise(rb_eTypeError, "DL::Symbol was expected");
 124    };
 125  
 126    return func;
 127  }
 128  
 129  VALUE
 130  rb_dlsym_s_allocate(VALUE klass)
 131  {
 132    VALUE obj;
 133    struct sym_data *data;
 134  
 135    obj = Data_Make_Struct(klass, struct sym_data, 0, dlsym_free, data);
 136    data->func = 0;
 137    data->name = 0;
 138    data->type = 0;
 139    data->len  = 0;
 140  
 141    return obj;
 142  }
 143  
 144  VALUE
 145  rb_dlsym_initialize(int argc, VALUE argv[], VALUE self)
 146  {
 147    VALUE addr, name, type;
 148    VALUE val;
 149    struct sym_data *data;
 150    void *saddr;
 151    const char *sname, *stype;
 152  
 153    rb_scan_args(argc, argv, "12", &addr, &name, &type);
 154  
 155    saddr = (void*)(DLNUM2LONG(rb_Integer(addr)));
 156    sname = NIL_P(name) ? NULL : StringValuePtr(name);
 157    stype = NIL_P(type) ? NULL : StringValuePtr(type);
 158  
 159    if( saddr ){
 160      Data_Get_Struct(self, struct sym_data, data);
 161      if( data->name ) free(data->name);
 162      if( data->type ) free(data->type);
 163      data->func = saddr;
 164      data->name = sname ? strdup(sname) : 0;
 165      data->type = stype ? strdup(stype) : 0;
 166      data->len  = stype ? strlen(stype) : 0;
 167    }
 168  
 169    return Qnil;
 170  }
 171  
 172  VALUE
 173  rb_s_dlsym_char2type(VALUE self, VALUE ch)
 174  {
 175    const char *type;
 176  
 177    type = char2type(StringValuePtr(ch)[0]);
 178  
 179    if (type == NULL)
 180      return Qnil;
 181    else
 182      return rb_str_new2(type);
 183  }
 184  
 185  VALUE
 186  rb_dlsym_name(VALUE self)
 187  {
 188    struct sym_data *sym;
 189  
 190    Data_Get_Struct(self, struct sym_data, sym);
 191    return sym->name ? rb_tainted_str_new2(sym->name) : Qnil;
 192  }
 193  
 194  VALUE
 195  rb_dlsym_proto(VALUE self)
 196  {
 197    struct sym_data *sym;
 198  
 199    Data_Get_Struct(self, struct sym_data, sym);
 200    return sym->type ? rb_tainted_str_new2(sym->type) : Qnil;
 201  }
 202  
 203  VALUE
 204  rb_dlsym_cproto(VALUE self)
 205  {
 206    struct sym_data *sym;
 207    const char *ptype, *typestr;
 208    size_t len;
 209    VALUE val;
 210  
 211    Data_Get_Struct(self, struct sym_data, sym);
 212  
 213    ptype = sym->type;
 214  
 215    if( ptype ){
 216      typestr = char2type(*ptype++);
 217      len = strlen(typestr);
 218      
 219      val = rb_tainted_str_new(typestr, len);
 220      if (typestr[len - 1] != '*')
 221        rb_str_cat(val, " ", 1);
 222  
 223      if( sym->name ){
 224        rb_str_cat2(val, sym->name);
 225      }
 226      else{
 227        rb_str_cat2(val, "(null)");
 228      };
 229      rb_str_cat(val, "(", 1);
 230      
 231      while (*ptype) {
 232        const char *ty = char2type(*ptype++);
 233        rb_str_cat2(val, ty);
 234        if (*ptype)
 235          rb_str_cat(val, ", ", 2);
 236      }
 237  
 238      rb_str_cat(val, ");", 2);
 239    }
 240    else{
 241      val = rb_tainted_str_new2("void (");
 242      if( sym->name ){
 243        rb_str_cat2(val, sym->name);
 244      }
 245      else{
 246        rb_str_cat2(val, "(null)");
 247      };
 248      rb_str_cat2(val, ")()");
 249    };
 250  
 251    return val;
 252  }
 253  
 254  VALUE
 255  rb_dlsym_inspect(VALUE self)
 256  {
 257    VALUE proto;
 258    VALUE val;
 259    char  *str;
 260    int str_size;
 261    struct sym_data *sym;
 262  
 263    Data_Get_Struct(self, struct sym_data, sym);
 264    proto = rb_dlsym_cproto(self);
 265  
 266    str_size = RSTRING(proto)->len + 100;
 267    str = dlmalloc(str_size);
 268    snprintf(str, str_size - 1,
 269             "#<DL::Symbol:0x%x func=0x%x '%s'>",
 270             sym, sym->func, RSTRING(proto)->ptr);
 271    val = rb_tainted_str_new2(str);
 272    dlfree(str);
 273  
 274    return val;
 275  }
 276  
 277  static int
 278  stack_size(struct sym_data *sym)
 279  {
 280    int i;
 281    int size;
 282  
 283    size = 0;
 284    for( i=1; i < sym->len; i++ ){
 285      switch(sym->type[i]){
 286      case 'C':
 287      case 'H':
 288      case 'I':
 289      case 'L':
 290        size += sizeof(long);
 291        break;
 292      case 'F':
 293        size += sizeof(float);
 294        break;
 295      case 'D':
 296        size += sizeof(double);
 297        break;
 298      case 'c':
 299      case 'h':
 300      case 'i':
 301      case 'l':
 302      case 'f':
 303      case 'd':
 304      case 'p':
 305      case 'P':
 306      case 's':
 307      case 'S':
 308      case 'a':
 309      case 'A':
 310        size += sizeof(void*);
 311        break;
 312      default:
 313        return -(sym->type[i]);
 314      }
 315    }
 316    return size;
 317  }
 318  
 319  VALUE
 320  rb_dlsym_call(int argc, VALUE argv[], VALUE self)
 321  {
 322    struct sym_data *sym;
 323    ANY_TYPE *args;
 324    ANY_TYPE *dargs;
 325    ANY_TYPE ret;
 326    int   *dtypes;
 327    VALUE val;
 328    VALUE dvals;
 329    int i;
 330    long ftype;
 331    void *func;
 332  
 333    Data_Get_Struct(self, struct sym_data, sym);
 334    DEBUG_CODE({
 335      printf("rb_dlsym_call(): type = '%s', func = 0x%x\n", sym->type, sym->func);
 336    });
 337    if( (sym->len - 1) != argc ){
 338      rb_raise(rb_eArgError, "%d arguments are needed", sym->len - 1);
 339    };
 340  
 341    ftype = 0;
 342    dvals = Qnil;
 343  
 344    args = ALLOC_N(ANY_TYPE, sym->len - 1);
 345    dargs = ALLOC_N(ANY_TYPE, sym->len - 1);
 346    dtypes = ALLOC_N(int, sym->len - 1);
 347  #define FREE_ARGS {xfree(args); xfree(dargs); xfree(dtypes);}
 348  
 349    for( i = sym->len - 2; i >= 0; i-- ){
 350      dtypes[i] = 0;
 351  
 352      switch( sym->type[i+1] ){
 353      case 'p':
 354        dtypes[i] = 'p';
 355      case 'P':
 356        {
 357          struct ptr_data *data;
 358          VALUE pval;
 359  
 360          if( argv[i] == Qnil ){
 361            ANY2P(args[i]) = DLVOIDP(0);
 362          }
 363          else{
 364            if( rb_obj_is_kind_of(argv[i], rb_cDLPtrData) ){
 365              pval = argv[i];
 366            }
 367            else{
 368              pval = rb_funcall(argv[i], rb_intern("to_ptr"), 0);
 369              if( !rb_obj_is_kind_of(pval, rb_cDLPtrData) ){
 370                rb_raise(rb_eDLTypeError, "unexpected type of argument #%d", i);
 371              };
 372            };
 373            Data_Get_Struct(pval, struct ptr_data, data);
 374            ANY2P(args[i]) = DLVOIDP(data->ptr);
 375          };
 376        };
 377        PUSH_P(ftype);
 378        break;
 379      case 'a':
 380        dtypes[i] = 'a';
 381      case 'A':
 382        if( argv[i] == Qnil ){
 383          ANY2P(args[i]) = DLVOIDP(0);
 384        }
 385        else{
 386          ANY2P(args[i]) = DLVOIDP(rb_ary2cary(0, argv[i], NULL));
 387        };
 388        PUSH_P(ftype);
 389        break;
 390      case 'C':
 391        ANY2C(args[i]) = DLCHAR(NUM2CHR(argv[i]));
 392        PUSH_C(ftype);
 393        break;
 394      case 'c':
 395        ANY2C(dargs[i]) = DLCHAR(NUM2CHR(argv[i]));
 396        ANY2P(args[i]) = DLVOIDP(&(ANY2C(dargs[i])));
 397        dtypes[i] = 'c';
 398        PUSH_P(ftype);
 399        break;
 400      case 'H':
 401        ANY2H(args[i]) = DLSHORT(NUM2CHR(argv[i]));
 402        PUSH_C(ftype);
 403        break;
 404      case 'h':
 405        ANY2H(dargs[i]) = DLSHORT(NUM2CHR(argv[i]));
 406        ANY2P(args[i]) = DLVOIDP(&(ANY2H(dargs[i])));
 407        dtypes[i] = 'h';
 408        PUSH_P(ftype);
 409        break;
 410      case 'I':
 411        ANY2I(args[i]) = DLINT(NUM2INT(argv[i]));
 412        PUSH_I(ftype);
 413        break;
 414      case 'i':
 415        ANY2I(dargs[i]) = DLINT(NUM2INT(argv[i]));
 416        ANY2P(args[i]) = DLVOIDP(&(ANY2I(dargs[i])));
 417        dtypes[i] = 'i';
 418        PUSH_P(ftype);
 419        break;
 420      case 'L':
 421        ANY2L(args[i]) = DLNUM2LONG(argv[i]);
 422        PUSH_L(ftype);
 423        break;
 424      case 'l':
 425        ANY2L(dargs[i]) = DLNUM2LONG(argv[i]);
 426        ANY2P(args[i]) = DLVOIDP(&(ANY2L(dargs[i])));
 427        dtypes[i] = 'l';
 428        PUSH_P(ftype);
 429        break;
 430      case 'F':
 431        Check_Type(argv[i], T_FLOAT);
 432        ANY2F(args[i]) = DLFLOAT(RFLOAT(argv[i])->value);
 433        PUSH_F(ftype);
 434        break;
 435      case 'f':
 436        Check_Type(argv[i], T_FLOAT);
 437        ANY2F(dargs[i]) = DLFLOAT(RFLOAT(argv[i])->value);
 438        ANY2P(args[i]) = DLVOIDP(&(ANY2F(dargs[i])));
 439        dtypes[i] = 'f';
 440        PUSH_P(ftype);
 441        break;
 442      case 'D':
 443        Check_Type(argv[i], T_FLOAT);
 444        ANY2D(args[i]) = RFLOAT(argv[i])->value;
 445        PUSH_D(ftype);
 446        break;
 447      case 'd':
 448        Check_Type(argv[i], T_FLOAT);
 449        ANY2D(dargs[i]) = RFLOAT(argv[i])->value;
 450        ANY2P(args[i]) = DLVOIDP(&(ANY2D(dargs[i])));
 451        dtypes[i] = 'd';
 452        PUSH_P(ftype);
 453        break;
 454      case 'S':
 455        if( argv[i] == Qnil ){
 456          ANY2S(args[i]) = DLSTR(0);
 457        }
 458        else{
 459          if( TYPE(argv[i]) != T_STRING ){
 460            rb_raise(rb_eDLError, "#%d must be a string",i);
 461          };
 462          ANY2S(args[i]) = DLSTR(RSTRING(argv[i])->ptr);
 463        };
 464        PUSH_P(ftype);
 465        break;
 466      case 's':
 467        if( TYPE(argv[i]) != T_STRING ){
 468          rb_raise(rb_eDLError, "#%d must be a string",i);
 469        };
 470        ANY2S(args[i]) = DLSTR(dlmalloc(RSTRING(argv[i])->len + 1));
 471        memcpy((char*)(ANY2S(args[i])), RSTRING(argv[i])->ptr, RSTRING(argv[i])->len + 1);
 472        dtypes[i] = 's';
 473        PUSH_P(ftype);
 474        break;
 475      default:
 476        FREE_ARGS;
 477        rb_raise(rb_eDLTypeError,
 478                 "unknown type '%c' of the return value.",
 479                 sym->type[i+1]);
 480      };
 481    };
 482  
 483    switch( sym->type[0] ){
 484    case '0':
 485      PUSH_0(ftype);
 486      break;
 487    case 'P':
 488    case 'p':
 489    case 'S':
 490    case 's':
 491    case 'A':
 492    case 'a':
 493      PUSH_P(ftype);
 494      break;
 495    case 'C':
 496    case 'c':
 497      PUSH_C(ftype);
 498      break;
 499    case 'H':
 500    case 'h':
 501      PUSH_H(ftype);
 502      break;
 503    case 'I':
 504    case 'i':
 505      PUSH_I(ftype);
 506      break;
 507    case 'L':
 508    case 'l':
 509      PUSH_L(ftype);
 510      break;
 511    case 'F':
 512    case 'f':
 513      PUSH_F(ftype);
 514      break;
 515    case 'D':
 516    case 'd':
 517      PUSH_D(ftype);
 518      break;
 519    default:
 520      FREE_ARGS;
 521      rb_raise(rb_eDLTypeError,
 522               "unknown type `%c' of the return value.",
 523               sym->type[0]);
 524    };
 525  
 526    func = sym->func;
 527  
 528  #if defined(DLSTACK)
 529    {
 530  #if defined(DLSTACK_SIZE)
 531    int  stk_size;
 532    long stack[DLSTACK_SIZE];
 533    long *sp;
 534  
 535    sp = stack;
 536    stk_size = stack_size(sym);
 537    if( stk_size < 0 ){
 538      FREE_ARGS;
 539      rb_raise(rb_eDLTypeError, "unknown type '%c'.", -stk_size);
 540    }
 541    else if( stk_size > (int)(DLSTACK_SIZE) ){
 542      FREE_ARGS;
 543      rb_raise(rb_eArgError, "too many arguments.");
 544    }
 545  #endif
 546  
 547    DLSTACK_START(sym);
 548  
 549  #if defined(DLSTACK_REVERSE)
 550    for( i = sym->len - 2; i >= 0; i-- )
 551  #else
 552    for( i = 0; i <= sym->len -2; i++ )
 553  #endif
 554    {
 555      switch( sym->type[i+1] ){
 556      case 'p':
 557      case 'P':
 558        DLSTACK_PUSH_P(ANY2P(args[i]));
 559        break;
 560      case 'a':
 561      case 'A':
 562        DLSTACK_PUSH_P(ANY2P(args[i]));
 563        break;
 564      case 'C':
 565        DLSTACK_PUSH_C(ANY2C(args[i]));
 566        break;
 567      case 'c':
 568        DLSTACK_PUSH_P(ANY2P(args[i]));
 569        break;
 570      case 'H':
 571        DLSTACK_PUSH_H(ANY2H(args[i]));
 572        break;
 573      case 'h':
 574        DLSTACK_PUSH_P(ANY2P(args[i]));
 575        break;
 576      case 'I':
 577        DLSTACK_PUSH_I(ANY2I(args[i]));
 578        break;
 579      case 'i':
 580        DLSTACK_PUSH_P(ANY2P(args[i]));
 581        break;
 582      case 'L':
 583        DLSTACK_PUSH_L(ANY2L(args[i]));
 584        break;
 585      case 'l':
 586        DLSTACK_PUSH_P(ANY2P(args[i]));
 587        break;
 588      case 'F':
 589        DLSTACK_PUSH_F(ANY2F(args[i]));
 590        break;
 591      case 'f':
 592        DLSTACK_PUSH_P(ANY2P(args[i]));
 593        break;
 594      case 'D':
 595        DLSTACK_PUSH_D(ANY2D(args[i]));
 596        break;
 597      case 'd':
 598        DLSTACK_PUSH_P(ANY2P(args[i]));
 599        break;
 600      case 'S':
 601      case 's':
 602        DLSTACK_PUSH_P(ANY2S(args[i]));
 603        break;
 604      };
 605    }
 606    DLSTACK_END(sym->type);
 607  
 608    {
 609      switch( sym->type[0] ){
 610      case '0':
 611        {
 612          void (*f)(DLSTACK_PROTO) = func;
 613          f(DLSTACK_ARGS);
 614        };
 615        break;
 616      case 'P':
 617      case 'p':
 618        {
 619          void * (*f)(DLSTACK_PROTO) = func;
 620          ret.p = f(DLSTACK_ARGS);
 621        };
 622        break;
 623      case 'C':
 624      case 'c':
 625        {
 626          char (*f)(DLSTACK_PROTO) = func;
 627          ret.c = f(DLSTACK_ARGS);
 628        };
 629        break;
 630      case 'H':
 631      case 'h':
 632        {
 633          short (*f)(DLSTACK_PROTO) = func;
 634          ret.h = f(DLSTACK_ARGS);
 635        };
 636        break;
 637      case 'I':
 638      case 'i':
 639        {
 640          int (*f)(DLSTACK_PROTO) = func;
 641          ret.i = f(DLSTACK_ARGS);
 642        };
 643        break;
 644      case 'L':
 645      case 'l':
 646        {
 647          long (*f)(DLSTACK_PROTO) = func;
 648          ret.l = f(DLSTACK_ARGS);
 649        };
 650        break;
 651      case 'F':
 652      case 'f':
 653        {
 654          float (*f)(DLSTACK_PROTO) = func;
 655          ret.f = f(DLSTACK_ARGS);
 656        };
 657        break;
 658      case 'D':
 659      case 'd':
 660        {
 661          double (*f)(DLSTACK_PROTO) = func;
 662          ret.d = f(DLSTACK_ARGS);
 663        };
 664        break;
 665      case 'S':
 666      case 's':
 667        {
 668          char * (*f)(DLSTACK_PROTO) = func;
 669          ret.s = f(DLSTACK_ARGS);
 670        };
 671        break;
 672      default:
 673        FREE_ARGS;
 674        rb_raise(rb_eDLTypeError, "unknown type `%c'", sym->type[0]);
 675      }
 676    }
 677    }
 678  #else /* defined(DLSTACK) */
 679    switch(ftype){
 680  #include "call.func"
 681    default:
 682      FREE_ARGS;
 683      rb_raise(rb_eDLTypeError, "unsupported function type `%s'", sym->type);
 684    };
 685  #endif /* defined(DLSTACK) */
 686  
 687    switch( sym->type[0] ){
 688    case '0':
 689      val = Qnil;
 690      break;
 691    case 'P':
 692      val = rb_dlptr_new((void*)(ANY2P(ret)), 0, 0);
 693      break;
 694    case 'p':
 695      val = rb_dlptr_new((void*)(ANY2P(ret)), 0, dlfree);
 696      break;
 697    case 'C':
 698    case 'c':
 699      val = CHR2FIX((char)(ANY2C(ret)));
 700      break;
 701    case 'H':
 702    case 'h':
 703      val = INT2NUM((short)(ANY2H(ret)));
 704      break;
 705    case 'I':
 706    case 'i':
 707      val = INT2NUM((int)(ANY2I(ret)));
 708      break;
 709    case 'L':
 710    case 'l':
 711      val = DLLONG2NUM((long)(ANY2L(ret)));
 712      break;
 713    case 'F':
 714    case 'f':
 715      val = rb_float_new((double)(ANY2F(ret)));
 716      break;
 717    case 'D':
 718    case 'd':
 719      val = rb_float_new((double)(ANY2D(ret)));
 720      break;
 721    case 'S':
 722      if( ANY2S(ret) ){
 723        val = rb_tainted_str_new2((char*)(ANY2S(ret)));
 724      }
 725      else{
 726        val = Qnil;
 727      };
 728      break;
 729    case 's':
 730      if( ANY2S(ret) ){
 731        val = rb_tainted_str_new2((char*)(ANY2S(ret)));
 732        DEBUG_CODE({
 733          printf("dlfree(%s)\n",(char*)(ANY2S(ret)));
 734        });
 735        dlfree((void*)(ANY2S(ret)));
 736      }
 737      else{
 738        val = Qnil;
 739      };
 740      break;
 741    default:
 742      FREE_ARGS;
 743      rb_raise(rb_eDLTypeError, "unknown type `%c'", sym->type[0]);
 744    };
 745  
 746    dvals = rb_ary_new();
 747    for( i = 0; i <= sym->len - 2; i++ ){
 748      if( dtypes[i] ){
 749        switch( dtypes[i] ){
 750        case 'c':
 751          rb_ary_push(dvals, CHR2FIX(*((char*)(ANY2P(args[i])))));
 752          break;
 753        case 'h':
 754          rb_ary_push(dvals, INT2NUM(*((short*)(ANY2P(args[i])))));
 755          break;
 756        case 'i':
 757          rb_ary_push(dvals, INT2NUM(*((int*)(ANY2P(args[i])))));
 758          break;
 759        case 'l':
 760          rb_ary_push(dvals, DLLONG2NUM(*((long*)(ANY2P(args[i])))));
 761          break;
 762        case 'f':
 763          rb_ary_push(dvals, rb_float_new(*((float*)(ANY2P(args[i])))));
 764          break;
 765        case 'd':
 766          rb_ary_push(dvals, rb_float_new(*((double*)(ANY2P(args[i])))));
 767          break;
 768        case 'p':
 769          rb_ary_push(dvals, rb_dlptr_new((void*)(ANY2P(args[i])), 0, 0));
 770          break;
 771        case 'a':
 772          rb_ary_push(dvals, rb_dlptr_new((void*)ANY2P(args[i]), 0, 0));
 773          break;
 774        case 's':
 775          rb_ary_push(dvals, rb_tainted_str_new2((char*)ANY2S(args[i])));
 776          DEBUG_CODE({
 777            printf("dlfree(%s)\n",(char*)ANY2S(args[i]));
 778          });
 779          dlfree((void*)ANY2S(args[i]));
 780          break;
 781        default:
 782          {
 783            char c = dtypes[i];
 784            FREE_ARGS;
 785            rb_raise(rb_eRuntimeError, "unknown argument type '%c'", i, c);
 786          };
 787        };
 788      }
 789      else{
 790        switch( sym->type[i+1] ){
 791        case 'A':
 792          dlfree((void*)ANY2P(args[i]));
 793          break;
 794        };
 795        rb_ary_push(dvals, argv[i]);
 796      };
 797    };
 798  
 799  #undef FREE_ARGS
 800    return rb_assoc_new(val,dvals);
 801  }
 802  
 803  VALUE
 804  rb_dlsym_to_i(VALUE self)
 805  {
 806    struct sym_data *sym;
 807  
 808    Data_Get_Struct(self, struct sym_data, sym);
 809    return DLLONG2NUM(sym);
 810  }
 811  
 812  VALUE
 813  rb_dlsym_to_ptr(VALUE self)
 814  {
 815    struct sym_data *sym;
 816  
 817    Data_Get_Struct(self, struct sym_data, sym);
 818    return rb_dlptr_new(sym->func, sizeof(freefunc_t), 0);
 819  }
 820  
 821  void
 822  Init_dlsym()
 823  {
 824    rb_cDLSymbol = rb_define_class_under(rb_mDL, "Symbol", rb_cObject);
 825    rb_define_singleton_method(rb_cDLSymbol, "allocate", rb_dlsym_s_allocate, 0);
 826    rb_define_singleton_method(rb_cDLSymbol, "char2type", rb_s_dlsym_char2type, 1);
 827    rb_define_method(rb_cDLSymbol, "initialize", rb_dlsym_initialize, -1);
 828    rb_define_method(rb_cDLSymbol, "call", rb_dlsym_call, -1);
 829    rb_define_method(rb_cDLSymbol, "[]",   rb_dlsym_call, -1);
 830    rb_define_method(rb_cDLSymbol, "name", rb_dlsym_name, 0);
 831    rb_define_method(rb_cDLSymbol, "proto", rb_dlsym_proto, 0);
 832    rb_define_method(rb_cDLSymbol, "cproto", rb_dlsym_cproto, 0);
 833    rb_define_method(rb_cDLSymbol, "inspect", rb_dlsym_inspect, 0);
 834    rb_define_method(rb_cDLSymbol, "to_s", rb_dlsym_cproto, 0);
 835    rb_define_method(rb_cDLSymbol, "to_ptr", rb_dlsym_to_ptr, 0);
 836    rb_define_method(rb_cDLSymbol, "to_i", rb_dlsym_to_i, 0);
 837  }