Пример #1
0
VALUE
rbffi_Function_ForProc(VALUE rbFunctionInfo, VALUE proc)
{
    VALUE callback, cbref, cbTable;
    Function* fp;

    cbref = RTEST(rb_ivar_defined(proc, id_cb_ref)) ? rb_ivar_get(proc, id_cb_ref) : Qnil;
    /* If the first callback reference has the same function function signature, use it */
    if (cbref != Qnil && CLASS_OF(cbref) == rbffi_FunctionClass) {
        Data_Get_Struct(cbref, Function, fp);
        if (fp->rbFunctionInfo == rbFunctionInfo) {
            return cbref;
        }
    }
    
    cbTable = RTEST(rb_ivar_defined(proc, id_cbtable)) ? rb_ivar_get(proc, id_cbtable) : Qnil;
    if (cbTable != Qnil && (callback = rb_hash_aref(cbTable, rbFunctionInfo)) != Qnil) {
        return callback;
    }
    
    /* No existing function for the proc with that signature, create a new one and cache it */
    callback = rbffi_Function_NewInstance(rbFunctionInfo, proc);
    if (cbref == Qnil) {
        /* If there is no other cb already cached for this proc, we can use the ivar slot */
        rb_ivar_set(proc, id_cb_ref, callback);
    } else {
        /* The proc instance has been used as more than one type of callback, store extras in a hash */
        cbTable = rb_hash_new();
        rb_ivar_set(proc, id_cbtable, cbTable);
        rb_hash_aset(cbTable, rbFunctionInfo, callback);
    }

    return callback;
}
Пример #2
0
/*
 * call-seq: get(pointer)
 * @param [AbstractMemory] pointer pointer on a {Struct}
 * @return [Function]
 * Get a {Function} from memory pointed by +pointer+.
 */
static VALUE
function_field_get(VALUE self, VALUE pointer)
{
    StructField* f;
    
    Data_Get_Struct(self, StructField, f);

    return rbffi_Function_NewInstance(f->rbType, (*rbffi_AbstractMemoryOps.pointer->get)(MEMORY(pointer), f->offset));
}
Пример #3
0
VALUE
rbffi_Function_ForProc(VALUE rbFunctionInfo, VALUE proc)
{
    VALUE callback;
    VALUE cbTable = RTEST(rb_ivar_defined(proc, id_cbtable)) ? rb_ivar_get(proc, id_cbtable) : Qnil;

    if (cbTable == Qnil) {
        cbTable = rb_hash_new();
        rb_ivar_set(proc, id_cbtable, cbTable);
    }

    callback = rb_hash_aref(cbTable, rbFunctionInfo);
    if (callback != Qnil) {
        return callback;
    }

    callback = rbffi_Function_NewInstance(rbFunctionInfo, proc);
    rb_hash_aset(cbTable, rbFunctionInfo, callback);
    return callback;
}
Пример #4
0
Файл: Types.c Проект: SFEley/ffi
VALUE
rbffi_NativeValue_ToRuby(Type* type, VALUE rbType, const void* ptr)
{
    switch (type->nativeType) {
        case NATIVE_VOID:
            return Qnil;
        case NATIVE_INT8:
          return INT2NUM((signed char) *(ffi_sarg *) ptr);
        case NATIVE_INT16:
          return INT2NUM((signed short) *(ffi_sarg *) ptr);
        case NATIVE_INT32:
          return INT2NUM((signed int) *(ffi_sarg *) ptr);
        case NATIVE_LONG:
            return LONG2NUM((signed long) *(ffi_sarg *) ptr);
        case NATIVE_INT64:
            return LL2NUM(*(signed long long *) ptr);

        case NATIVE_UINT8:
          return UINT2NUM((unsigned char) *(ffi_arg *) ptr);
        case NATIVE_UINT16:
          return UINT2NUM((unsigned short) *(ffi_arg *) ptr);
        case NATIVE_UINT32:
          return UINT2NUM((unsigned int) *(ffi_arg *) ptr);
        case NATIVE_ULONG:
            return ULONG2NUM((unsigned long) *(ffi_arg *) ptr);
        case NATIVE_UINT64:
            return ULL2NUM(*(unsigned long long *) ptr);

        case NATIVE_FLOAT32:
            return rb_float_new(*(float *) ptr);
        case NATIVE_FLOAT64:
            return rb_float_new(*(double *) ptr);

        case NATIVE_LONGDOUBLE:
	  return rbffi_longdouble_new(*(long double *) ptr);

        case NATIVE_STRING:
            return (*(void **) ptr != NULL) ? rb_tainted_str_new2(*(char **) ptr) : Qnil;
        case NATIVE_POINTER:
            return rbffi_Pointer_NewInstance(*(void **) ptr);
        case NATIVE_BOOL:
            return ((unsigned char) *(ffi_arg *) ptr) ? Qtrue : Qfalse;
        
        case NATIVE_FUNCTION:
        case NATIVE_CALLBACK: {
            return *(void **) ptr != NULL 
                    ? rbffi_Function_NewInstance(rbType, rbffi_Pointer_NewInstance(*(void **) ptr))
                    : Qnil;
        }

        case NATIVE_STRUCT: {
            StructByValue* sbv = (StructByValue *)type;
            AbstractMemory* mem;
            VALUE rbMemory = rbffi_MemoryPointer_NewInstance(1, sbv->base.ffiType->size, false);

            Data_Get_Struct(rbMemory, AbstractMemory, mem);
            memcpy(mem->address, ptr, sbv->base.ffiType->size);
            RB_GC_GUARD(rbMemory);
            RB_GC_GUARD(rbType);

            return rb_class_new_instance(1, &rbMemory, sbv->rbStructClass);
        }

        case NATIVE_MAPPED: {
            /*
             * For mapped types, first convert to the real native type, then upcall to
             * ruby to convert to the expected return type
             */
            MappedType* m = (MappedType *) type;
            VALUE values[2], rbReturnValue;

            values[0] = rbffi_NativeValue_ToRuby(m->type, m->rbType, ptr);
            values[1] = Qnil;
            

            rbReturnValue = rb_funcall2(m->rbConverter, id_from_native, 2, values);
            RB_GC_GUARD(values[0]);
            RB_GC_GUARD(rbType);
            
            return rbReturnValue;
        }
    
        default:
            rb_raise(rb_eRuntimeError, "Unknown type: %d", type->nativeType);
            return Qnil;
    }
}