コード例 #1
0
ファイル: cfunc_closure.c プロジェクト: asfluido/mruby-cfunc
void
cfunc_closure_call_binding(ffi_cif *cif, void *ret, void **args, void *self_)
{
    mrb_value self = mrb_obj_value(self_);
    struct cfunc_closure_data *data = DATA_PTR(self);

    int ai = mrb_gc_arena_save(data->mrb);

    mrb_value *ary = mrb_malloc(data->mrb, sizeof(mrb_value) * data->argc);
    int i;
    for (i = 0; i < data->argc; ++i) {
        // TODO: I felt too much consume memory
        void *p = mrb_malloc(data->mrb, data->arg_ffi_types[i]->size);
        memcpy(p, args[i], data->arg_ffi_types[i]->size);
        mrb_value pointer = cfunc_pointer_new_with_pointer(data->mrb, p, true);
        ary[i] = mrb_funcall(data->mrb, data->arg_types[i], "refer", 1, pointer);
    }

    mrb_value block = mrb_iv_get(data->mrb, self, mrb_intern_cstr(data->mrb, "@block"));
    mrb_value result = mrb_funcall_argv(data->mrb, block, mrb_intern_cstr(data->mrb, "call"), data->argc, ary);
    mrb_free(data->mrb, ary);

    mrb_value ret_pointer = cfunc_pointer_new_with_pointer(data->mrb, ret, false);
    mrb_funcall(data->mrb, data->return_type, "set", 2, ret_pointer, result);
    
    mrb_gc_arena_restore(data->mrb, ai);
}
コード例 #2
0
static mrb_value
cfunc_string_to_pointer(mrb_state *mrb, mrb_value self)
{
    mrb_value ptr = cfunc_pointer_new_with_pointer(mrb, &RSTRING_PTR(self), false);
    mrb_obj_iv_set(mrb, mrb_obj_ptr(ptr), mrb_intern(mrb, "parent_pointer"), self); // keep for GC
    return ptr;
}
コード例 #3
0
ファイル: cfunc_type.c プロジェクト: asfluido/mruby-cfunc
// nil specific
mrb_value
cfunc_nil_addr(mrb_state *mrb, mrb_value self)
{
    struct cfunc_type_data *data = (struct cfunc_type_data*)DATA_PTR(self);

    mrb_value ptr;
    if(data->refer) {
        ptr = cfunc_pointer_new_with_pointer(mrb, data->value._pointer, false);
    }
    else {
        ptr = cfunc_pointer_new_with_pointer(mrb, &data->value._pointer, false);
    }

    mrb_obj_iv_set(mrb, mrb_obj_ptr(ptr), mrb_intern_cstr(mrb, "parent_pointer"), self); // keep for GC

    return ptr;
}
コード例 #4
0
mrb_value
cfunc_pointer_offset(mrb_state *mrb, mrb_value self)
{
    struct cfunc_type_data *data = DATA_PTR(self);
    int offset;
    mrb_get_args(mrb, "i", &offset);

    mrb_value ptr = cfunc_pointer_new_with_pointer(mrb, (void*)((uint8_t*)get_cfunc_pointer_data(data) + offset), false);
    mrb_obj_iv_set(mrb, mrb_obj_ptr(ptr), mrb_intern(mrb, "parent_pointer"), self); // keep for GC
    return ptr;
}
コード例 #5
0
static mrb_value
cfunc_call(mrb_state *mrb, mrb_value self)
{
    int margc;
    mrb_value mresult_type, mname, *margs;
    mrb_get_args(mrb, "oo*", &mresult_type, &mname, &margs, &margc);
        
    void *dlh = dlopen(NULL, RTLD_LAZY);
    void *fp = dlsym(dlh, RSTRING_PTR(mname));
    
    ffi_type **args = malloc(sizeof(ffi_type*) * margc);
    void **values = malloc(sizeof(void*) * margc);
    mrb_sym to_pointer = mrb_intern(mrb, "to_pointer");

    for(int i = 0; i < margc; ++i) {
        if(!mrb_respond_to(mrb, margs[i], to_pointer)) {
            // Todo: should free some malloc-ed pointers
            mrb_raise(mrb, E_TYPE_ERROR, "ignore argument type");
        }
        args[i] = mrb_value_to_mrb_ffi_type(mrb, margs[i])->ffi_type_value;
        values[i] = mobi_pointer_ptr(mrb_funcall(mrb, margs[i], "to_pointer", 0));
    }
    
    ffi_type *result_type = rclass_to_mrb_ffi_type(mrb, mrb_class_ptr(mresult_type))->ffi_type_value;
    if (result_type == NULL) {
        mrb_raise(mrb, E_ARGUMENT_ERROR, "ignore return type");
    }
    
    mrb_value mresult = mrb_nil_value();
    ffi_cif cif;
    if (ffi_prep_cif(&cif, FFI_DEFAULT_ABI, margc, result_type, args) == FFI_OK) {
        void *result = result_type->size ? malloc(result_type->size) : NULL;
        ffi_call(&cif, fp, result, values);
        
        if(result) {
            mrb_value result_ptr = cfunc_pointer_new_with_pointer(mrb, result, 1);
            mresult = mrb_funcall(mrb, mresult_type, "refer", 1, result_ptr);
        }
    }
    else {
        // todo
        mrb_raise(mrb, E_NAME_ERROR, "can't find C function");
    }

cfunc_call_exit:
    free(values);
    free(args);
    return mresult;
}
コード例 #6
0
mrb_value
cfunc_pointer_to_pointer(mrb_state *mrb, mrb_value self)
{
    struct cfunc_type_data *data = DATA_PTR(self);
    void *ptr = NULL;
    if(data->refer) {
        ptr = data->value._pointer;
    }
    else {
        ptr = &data->value._pointer;
    }

    mrb_value obj = cfunc_pointer_new_with_pointer(mrb, ptr, 0);
    mrb_obj_iv_set(mrb, mrb_obj_ptr(obj), mrb_intern(mrb, "parent_pointer"), self); // keep for GC
    return obj;
}
コード例 #7
0
ファイル: cfunc_call.c プロジェクト: a-bx/mruby-cfunc
static mrb_value
cfunc_call(mrb_state *mrb, mrb_value self)
{
    int margc;
    mrb_value mresult_type, mname, *margs;
    void **values = NULL;
    ffi_type **args = NULL;

    mrb_get_args(mrb, "oo*", &mresult_type, &mname, &margs, &margc);

    void *fp = NULL;
    if(mrb_string_p(mname) || mrb_symbol_p(mname)) {
        void *dlh = dlopen(NULL, RTLD_LAZY);
        fp = dlsym(dlh, mrb_string_value_ptr(mrb, mname));
        dlclose(dlh);
    }
    else {
        fp = cfunc_pointer_ptr(mname);
    }

    if(fp == NULL) {
        mrb_raisef(mrb, E_NAME_ERROR, "can't find C function %s", mrb_string_value_ptr(mrb, mname));
        goto cfunc_call_exit;
    }

    args = malloc(sizeof(ffi_type*) * margc);
    values = malloc(sizeof(void*) * margc);
    mrb_sym sym_to_ffi_value = mrb_intern(mrb, "to_ffi_value");

    mrb_value nil_ary[1];
    nil_ary[0] = mrb_nil_value();
    for(int i = 0; i < margc; ++i) {
        if(mrb_respond_to(mrb, margs[i], sym_to_ffi_value)) {
            args[i] = mrb_value_to_mrb_ffi_type(mrb, margs[i])->ffi_type_value;
            values[i] = cfunc_pointer_ptr(mrb_funcall_argv(mrb, margs[i], sym_to_ffi_value, 1, nil_ary));
        }
        else {
            cfunc_mrb_raise_without_jump(mrb, E_TYPE_ERROR, "ignore argument type %s", mrb_obj_classname(mrb, margs[i]));
            goto cfunc_call_exit;
        }
    }

    ffi_type *result_type = rclass_to_mrb_ffi_type(mrb, mrb_class_ptr(mresult_type))->ffi_type_value;
    if (result_type == NULL) {
        cfunc_mrb_raise_without_jump(mrb, E_ARGUMENT_ERROR, "ignore return type %s", mrb_class_name(mrb, mrb_class_ptr(mresult_type)));
        goto cfunc_call_exit;
    }

    mrb_value mresult = mrb_nil_value();
    ffi_cif cif;
    if (ffi_prep_cif(&cif, FFI_DEFAULT_ABI, margc, result_type, args) == FFI_OK) {
        void *result;
        if(result_type->size > sizeof(long)) {
            result = malloc(result_type->size);
        }
        else if(result_type->size) {
            result = malloc(sizeof(long));
        }
        else {
            result = NULL;
        }
        ffi_call(&cif, fp, result, values);

        if(result) {
            mrb_value result_ptr = cfunc_pointer_new_with_pointer(mrb, result, true);
            mresult = mrb_funcall(mrb, mresult_type, "refer", 1, result_ptr);
        }
    }
    else {
        mrb_raisef(mrb, E_NAME_ERROR, "Can't find C function %s", mname);
        goto cfunc_call_exit;
    }

cfunc_call_exit:
    free(values);
    free(args);
    return mresult;
}
コード例 #8
0
static mrb_value
cfunc_pointer_data_to_mrb(mrb_state *mrb, struct cfunc_type_data *data)
{
    return cfunc_pointer_new_with_pointer(mrb, get_cfunc_pointer_data(data), false);
}
コード例 #9
0
static mrb_value
cfunc_pointer_c_to_mrb(mrb_state *mrb, void* p)
{
    return cfunc_pointer_new_with_pointer(mrb, *(void**)p, false);
}