ext/dl/handle.c


DEFINITIONS

This source file includes following functions.
  1. dlhandle_free
  2. rb_dlhandle_close
  3. rb_dlhandle_s_allocate
  4. rb_dlhandle_initialize
  5. rb_dlhandle_enable_close
  6. rb_dlhandle_disable_close
  7. rb_dlhandle_to_i
  8. rb_dlhandle_to_ptr
  9. rb_dlhandle_sym
  10. Init_dlhandle


   1  /* -*- C -*-
   2   * $Id: handle.c,v 1.4 2002/08/05 01:24:13 ttate Exp $
   3   */
   4  
   5  #include <ruby.h>
   6  #include "dl.h"
   7  
   8  VALUE rb_cDLHandle;
   9  
  10  void
  11  dlhandle_free(struct dl_handle *dlhandle)
  12  {
  13    if( dlhandle->ptr && dlhandle->open && dlhandle->enable_close ){
  14      dlclose(dlhandle->ptr);
  15    };
  16  }
  17  
  18  VALUE
  19  rb_dlhandle_close(VALUE self)
  20  {
  21    struct dl_handle *dlhandle;
  22  
  23    Data_Get_Struct(self, struct dl_handle, dlhandle);
  24    dlhandle->open = 0;
  25    return INT2NUM(dlclose(dlhandle->ptr));
  26  }
  27  
  28  VALUE
  29  rb_dlhandle_s_allocate(VALUE klass)
  30  {
  31    VALUE obj;
  32    struct dl_handle *dlhandle;
  33  
  34    obj = Data_Make_Struct(rb_cDLHandle, struct dl_handle, 0,
  35                           dlhandle_free, dlhandle);
  36    dlhandle->ptr  = 0;
  37    dlhandle->open = 0;
  38    dlhandle->enable_close = 0;
  39  
  40    return obj;
  41  }
  42  
  43  VALUE
  44  rb_dlhandle_initialize(int argc, VALUE argv[], VALUE self)
  45  {
  46    void *ptr;
  47    struct dl_handle *dlhandle;
  48    VALUE lib, flag;
  49    char  *clib;
  50    int   cflag;
  51    const char *err;
  52  
  53    switch( rb_scan_args(argc, argv, "11", &lib, &flag) ){
  54    case 1:
  55      clib = StringValuePtr(lib);
  56      cflag = RTLD_LAZY | RTLD_GLOBAL;
  57      break;
  58    case 2:
  59      clib = StringValuePtr(lib);
  60      cflag = NUM2INT(flag);
  61      break;
  62    default:
  63      rb_bug("rb_dlhandle_new");
  64    };
  65  
  66    ptr = dlopen(clib, cflag);
  67  #if defined(HAVE_DLERROR)
  68    if( (err = dlerror()) ){
  69      rb_raise(rb_eRuntimeError, err);
  70    };
  71  #else
  72    if( !ptr ){
  73      err = dlerror();
  74      rb_raise(rb_eRuntimeError, err);
  75    };
  76  #endif
  77    Data_Get_Struct(self, struct dl_handle, dlhandle);
  78    if( dlhandle->ptr && dlhandle->open && dlhandle->enable_close ){
  79      dlclose(dlhandle->ptr);
  80    }
  81    dlhandle->ptr = ptr;
  82    dlhandle->open = 1;
  83    dlhandle->enable_close = 0;
  84  
  85    if( rb_block_given_p() ){
  86      rb_ensure(rb_yield, self, rb_dlhandle_close, self);
  87    };
  88  
  89    return Qnil;
  90  }
  91  
  92  VALUE
  93  rb_dlhandle_enable_close(VALUE self)
  94  {
  95    struct dl_handle *dlhandle;
  96  
  97    Data_Get_Struct(self, struct dl_handle, dlhandle);
  98    dlhandle->enable_close = 1;
  99    return Qnil;
 100  }
 101  
 102  VALUE
 103  rb_dlhandle_disable_close(VALUE self)
 104  {
 105    struct dl_handle *dlhandle;
 106  
 107    Data_Get_Struct(self, struct dl_handle, dlhandle);
 108    dlhandle->enable_close = 0;
 109    return Qnil;
 110  }
 111  
 112  VALUE
 113  rb_dlhandle_to_i(VALUE self)
 114  {
 115    struct dl_handle *dlhandle;
 116  
 117    Data_Get_Struct(self, struct dl_handle, dlhandle);
 118    return DLLONG2NUM(dlhandle);
 119  }
 120  
 121  VALUE
 122  rb_dlhandle_to_ptr(VALUE self)
 123  {
 124    struct dl_handle *dlhandle;
 125  
 126    Data_Get_Struct(self, struct dl_handle, dlhandle);
 127    return rb_dlptr_new(dlhandle, sizeof(dlhandle), 0);
 128  }
 129  
 130  VALUE
 131  rb_dlhandle_sym(int argc, VALUE argv[], VALUE self)
 132  {
 133    VALUE sym, type;
 134    void (*func)();
 135    VALUE val;
 136    struct sym_data *data;
 137    int *ctypes;
 138    int i, ctypes_len;
 139    struct dl_handle *dlhandle;
 140    void *handle;
 141    const char *name, *stype;
 142    const char *err;
 143  
 144    if( rb_scan_args(argc, argv, "11", &sym, &type) == 2 ){
 145      stype = StringValuePtr(type);
 146    }
 147    else{
 148      stype = NULL;
 149    };
 150  
 151    if( sym == Qnil ){
 152  #if defined(RTLD_NEXT)
 153      name = RTLD_NEXT;
 154  #else
 155      name = NULL;
 156  #endif
 157    }
 158    else{
 159      name = StringValuePtr(sym);
 160    };
 161  
 162  
 163    Data_Get_Struct(self, struct dl_handle, dlhandle);
 164    if( ! dlhandle->open ){
 165      rb_raise(rb_eRuntimeError, "Closed handle.");
 166    }
 167    handle = dlhandle->ptr;
 168  
 169    func = dlsym(handle, name);
 170  #if defined(HAVE_DLERROR)
 171    if( (err = dlerror()) && (!func) )
 172  #else
 173    if( !func )
 174  #endif
 175    {
 176  #if defined(__CYGWIN__) || defined(WIN32) || defined(__MINGW32__)
 177      {
 178        int  len = strlen(name);
 179        char *name_a = (char*)dlmalloc(len+2);
 180        strcpy(name_a, name);
 181        name_a[len]   = 'A';
 182        name_a[len+1] = '\0';
 183        func = dlsym(handle, name_a);
 184        dlfree(name_a);
 185  #if defined(HAVE_DLERROR)
 186        if( (err = dlerror()) && (!func) )
 187  #else
 188        if( !func )
 189  #endif
 190        {
 191          rb_raise(rb_eRuntimeError, "Unknown symbol \"%sA\".", name);
 192        };
 193      }
 194  #else
 195      rb_raise(rb_eRuntimeError, "Unknown symbol \"%s\".", name);
 196  #endif
 197    };
 198    val = rb_dlsym_new(func, name, stype);
 199  
 200    return val;
 201  }
 202  
 203  void
 204  Init_dlhandle()
 205  {
 206    rb_cDLHandle = rb_define_class_under(rb_mDL, "Handle", rb_cObject);
 207    rb_define_singleton_method(rb_cDLHandle, "allocate", rb_dlhandle_s_allocate, 0);
 208    rb_define_method(rb_cDLHandle, "initialize", rb_dlhandle_initialize, -1);
 209    rb_define_method(rb_cDLHandle, "to_i", rb_dlhandle_to_i, 0);
 210    rb_define_method(rb_cDLHandle, "to_ptr", rb_dlhandle_to_ptr, 0);
 211    rb_define_method(rb_cDLHandle, "close", rb_dlhandle_close, 0);
 212    rb_define_method(rb_cDLHandle, "sym",  rb_dlhandle_sym, -1);
 213    rb_define_method(rb_cDLHandle, "[]",  rb_dlhandle_sym, -1);
 214    rb_define_method(rb_cDLHandle, "disable_close", rb_dlhandle_disable_close, 0);
 215    rb_define_method(rb_cDLHandle, "enable_close", rb_dlhandle_enable_close, 0);
 216  }