読者です 読者をやめる 読者になる 読者になる


……面倒になったのでコードはって終わり。

#include <ffi.h>

ffi_type *get_ffi_type(reflection_type_t type) {
    switch (type) {
    case R_CHAR:
        return &ffi_type_sint8;
    case R_INT:
        return &ffi_type_sint32;
    case R_FLOAT:
        return &ffi_type_float;
    case R_PTR:
        return &ffi_type_pointer;
    default:
        return &ffi_type_void;
    }
}

int reflection_dispatch(
    reflection_t* ref, const char* name, reflection_type_t rtype,
    int arg_num, reflection_value_t* args, reflection_type_t* types,
    reflection_value_t* ret)
{
    reflection_sym_t** asym =
        (reflection_sym_t**)htab_find_slot(ref->syms, name, NO_INSERT);
    void* fp = NULL;

    if (!asym) {
#ifdef __USE_GNU
        fp = (void*)dlsym(RTLD_DEFAULT, name);
#endif
        if (fp == 0) return 1;
    }
    else {
        fp = (void*)((*asym)->fp);
    }

    {
        ffi_cif cif;
        ffi_type* as[32];
        void* vs[32];
        ffi_arg rv;
        ffi_type* rt;
        int i;

        for (i = 0; i < arg_num; i++) {
            as[i] = get_ffi_type(types[i]);
            if (as[i] == &ffi_type_void) return 1;
            vs[i] = &args[i];
        }

        rt = get_ffi_type(rtype);
        if (ffi_prep_cif(&cif, FFI_DEFAULT_ABI, arg_num, rt, as) != FFI_OK) {
            return 1;
        }

        ffi_call(&cif, FFI_FN(fp), &rv, vs);

        if (rtype != R_VOID) {
            *ret = *(reflection_value_t*)&rv;
        }

        return 0;
    }
}
なにかあれば下記メールアドレスへ。
shinichiro.hamaji _at_ gmail.com
shinichiro.h