int main (void) { ffi_cif cif; #ifndef USING_MMAP static ffi_closure cl; #endif ffi_closure *pcl; void* args[1]; ffi_type* arg_types[1]; #ifdef USING_MMAP pcl = allocate_mmap (sizeof(ffi_closure)); #else pcl = &cl; #endif arg_types[0] = NULL; args[0] = NULL; CHECK(ffi_prep_cif(&cif, 255, 0, &ffi_type_void, arg_types) == FFI_BAD_ABI); CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 0, &ffi_type_void, arg_types) == FFI_OK); cif.abi= 255; CHECK(ffi_prep_closure(pcl, &cif, dummy_fn, NULL) == FFI_BAD_ABI); exit(0); }
int main (void) { ffi_cif cif; #ifndef USING_MMAP static ffi_closure cl; #endif ffi_closure *pcl; ffi_type * cl_arg_types[2]; unsigned short res; #ifdef USING_MMAP pcl = allocate_mmap (sizeof(ffi_closure)); #else pcl = &cl; #endif cl_arg_types[0] = &ffi_type_ushort; cl_arg_types[1] = NULL; /* Initialize the cif */ CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, &ffi_type_ushort, cl_arg_types) == FFI_OK); CHECK(ffi_prep_closure(pcl, &cif, cls_ret_ushort_fn, NULL) == FFI_OK); res = (*((cls_ret_ushort)pcl))(65535); /* { dg-output "65535: 65535" } */ printf("res: %d\n",res); /* { dg-output "\nres: 65535" } */ exit(0); }
static bool closure_prep(ffi_cif* cif, void* code, Closure* closure, char* errbuf, size_t errbufsize) { ffi_status status; status = ffi_prep_closure(code, cif, closure_invoke, closure); switch (status) { case FFI_OK: return true; case FFI_BAD_ABI: snprintf(errbuf, errbufsize, "Invalid ABI specified"); //throwException(env, IllegalArgument, "Invalid ABI specified"); return false; case FFI_BAD_TYPEDEF: snprintf(errbuf, errbufsize, "Invalid argument type specified"); //throwException(env, IllegalArgument, "Invalid argument type specified"); return false; default: snprintf(errbuf, errbufsize, "Unknown FFI error"); //throwException(env, IllegalArgument, "Unknown FFI error"); return false; } }
int main (void) { ffi_cif cif; #ifndef USING_MMAP static ffi_closure cl; #endif ffi_closure *pcl; void* args_dbl[5]; ffi_type* cls_struct_fields[5]; ffi_type cls_struct_type; ffi_type* dbl_arg_types[5]; #ifdef USING_MMAP pcl = allocate_mmap (sizeof(ffi_closure)); #else pcl = &cl; #endif cls_struct_type.size = 0; cls_struct_type.alignment = 0; cls_struct_type.type = FFI_TYPE_STRUCT; cls_struct_type.elements = cls_struct_fields; struct cls_struct_7byte g_dbl = { 127, 120, 1, 254 }; struct cls_struct_7byte f_dbl = { 12, 128, 9, 255 }; struct cls_struct_7byte res_dbl; cls_struct_fields[0] = &ffi_type_ushort; cls_struct_fields[1] = &ffi_type_ushort; cls_struct_fields[2] = &ffi_type_uchar; cls_struct_fields[3] = &ffi_type_ushort; cls_struct_fields[4] = NULL; dbl_arg_types[0] = &cls_struct_type; dbl_arg_types[1] = &cls_struct_type; dbl_arg_types[2] = NULL; CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type, dbl_arg_types) == FFI_OK); args_dbl[0] = &g_dbl; args_dbl[1] = &f_dbl; args_dbl[2] = NULL; ffi_call(&cif, FFI_FN(cls_struct_7byte_fn), &res_dbl, args_dbl); /* { dg-output "127 120 1 254 12 128 9 255: 139 248 10 509" } */ printf("res: %d %d %d %d\n", res_dbl.a, res_dbl.b, res_dbl.c, res_dbl.d); /* { dg-output "\nres: 139 248 10 509" } */ CHECK(ffi_prep_closure(pcl, &cif, cls_struct_7byte_gn, NULL) == FFI_OK); res_dbl = ((cls_struct_7byte(*)(cls_struct_7byte, cls_struct_7byte))(pcl))(g_dbl, f_dbl); /* { dg-output "\n127 120 1 254 12 128 9 255: 139 248 10 509" } */ printf("res: %d %d %d %d\n", res_dbl.a, res_dbl.b, res_dbl.c, res_dbl.d); /* { dg-output "\nres: 139 248 10 509" } */ exit(0); }
int main (void) { ffi_cif cif; #ifndef USING_MMAP static ffi_closure cl; #endif ffi_closure *pcl; void* args_dbl[5]; ffi_type* cls_struct_fields[4]; ffi_type cls_struct_type; ffi_type* dbl_arg_types[5]; #ifdef USING_MMAP pcl = allocate_mmap (sizeof(ffi_closure)); #else pcl = &cl; #endif cls_struct_type.size = 0; cls_struct_type.alignment = 0; cls_struct_type.type = FFI_TYPE_STRUCT; cls_struct_type.elements = cls_struct_fields; struct cls_struct_align g_dbl = { 12, (void *)4951, 127 }; struct cls_struct_align f_dbl = { 1, (void *)9320, 13 }; struct cls_struct_align res_dbl; cls_struct_fields[0] = &ffi_type_uchar; cls_struct_fields[1] = &ffi_type_pointer; cls_struct_fields[2] = &ffi_type_uchar; cls_struct_fields[3] = NULL; dbl_arg_types[0] = &cls_struct_type; dbl_arg_types[1] = &cls_struct_type; dbl_arg_types[2] = NULL; CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type, dbl_arg_types) == FFI_OK); args_dbl[0] = &g_dbl; args_dbl[1] = &f_dbl; args_dbl[2] = NULL; ffi_call(&cif, FFI_FN(cls_struct_align_fn), &res_dbl, args_dbl); /* { dg-output "12 4951 127 1 9320 13: 13 14271 140" } */ printf("res: %d %d %d\n", res_dbl.a, (size_t)res_dbl.b, res_dbl.c); /* { dg-output "\nres: 13 14271 140" } */ CHECK(ffi_prep_closure(pcl, &cif, cls_struct_align_gn, NULL) == FFI_OK); res_dbl = ((cls_struct_align(*)(cls_struct_align, cls_struct_align))(pcl))(g_dbl, f_dbl); /* { dg-output "\n12 4951 127 1 9320 13: 13 14271 140" } */ printf("res: %d %d %d\n", res_dbl.a, (size_t)res_dbl.b, res_dbl.c); /* { dg-output "\nres: 13 14271 140" } */ exit(0); }
int main (void) { ffi_cif cif; #ifndef USING_MMAP static ffi_closure cl; #endif ffi_closure *pcl; void* args_dbl[3]; ffi_type* cls_struct_fields[4]; ffi_type cls_struct_type; ffi_type* dbl_arg_types[3]; #ifdef USING_MMAP pcl = allocate_mmap (sizeof(ffi_closure)); #else pcl = &cl; #endif cls_struct_type.size = 0; cls_struct_type.alignment = 0; cls_struct_type.type = FFI_TYPE_STRUCT; cls_struct_type.elements = cls_struct_fields; struct cls_struct_20byte g_dbl = { 1, 2.0, 3.0 }; struct cls_struct_20byte f_dbl = { 4, 5.0, 7.0 }; struct cls_struct_20byte res_dbl; cls_struct_fields[0] = &ffi_type_uint32; cls_struct_fields[1] = &ffi_type_double; cls_struct_fields[2] = &ffi_type_double; cls_struct_fields[3] = NULL; dbl_arg_types[0] = &cls_struct_type; dbl_arg_types[1] = &cls_struct_type; dbl_arg_types[2] = NULL; CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type, dbl_arg_types) == FFI_OK); args_dbl[0] = &g_dbl; args_dbl[1] = &f_dbl; args_dbl[2] = NULL; ffi_call(&cif, FFI_FN(cls_struct_20byte_fn), &res_dbl, args_dbl); /* { dg-output "1 2 3 4 5 7: 5 7 10" } */ printf("res: %d %g %g\n", res_dbl.a, res_dbl.b, res_dbl.c); /* { dg-output "\nres: 5 7 10" } */ CHECK(ffi_prep_closure(pcl, &cif, cls_struct_20byte_gn, NULL) == FFI_OK); res_dbl = ((cls_struct_20byte(*)(cls_struct_20byte, cls_struct_20byte))(pcl))(g_dbl, f_dbl); /* { dg-output "\n1 2 3 4 5 7: 5 7 10" } */ printf("res: %d %g %g\n", res_dbl.a, res_dbl.b, res_dbl.c); /* { dg-output "\nres: 5 7 10" } */ exit(0); }
static VALUE initialize(int rbargc, VALUE argv[], VALUE self) { VALUE ret; VALUE args; VALUE abi; fiddle_closure * cl; ffi_cif * cif; ffi_closure *pcl; ffi_status result; int i, argc; if (2 == rb_scan_args(rbargc, argv, "21", &ret, &args, &abi)) abi = INT2NUM(FFI_DEFAULT_ABI); Check_Type(args, T_ARRAY); argc = RARRAY_LENINT(args); TypedData_Get_Struct(self, fiddle_closure, &closure_data_type, cl); cl->argv = (ffi_type **)xcalloc(argc + 1, sizeof(ffi_type *)); for (i = 0; i < argc; i++) { int type = NUM2INT(RARRAY_PTR(args)[i]); cl->argv[i] = INT2FFI_TYPE(type); } cl->argv[argc] = NULL; rb_iv_set(self, "@ctype", ret); rb_iv_set(self, "@args", args); cif = &cl->cif; pcl = cl->pcl; result = ffi_prep_cif(cif, NUM2INT(abi), argc, INT2FFI_TYPE(NUM2INT(ret)), cl->argv); if (FFI_OK != result) rb_raise(rb_eRuntimeError, "error prepping CIF %d", result); #ifndef DONT_USE_FFI_CLOSURE_ALLOC result = ffi_prep_closure_loc(pcl, cif, callback, (void *)self, cl->code); #else result = ffi_prep_closure(pcl, cif, callback, (void *)self); cl->code = (void *)pcl; mprotect(pcl, sizeof(pcl), PROT_READ | PROT_EXEC); #endif if (FFI_OK != result) rb_raise(rb_eRuntimeError, "error prepping closure %d", result); return self; }
int main (void) { ffi_cif cif; #ifndef USING_MMAP static ffi_closure cl; #endif ffi_closure *pcl; void* args_dbl[5]; ffi_type* cls_struct_fields[4]; ffi_type cls_struct_type; ffi_type* dbl_arg_types[5]; #ifdef USING_MMAP pcl = allocate_mmap (sizeof(ffi_closure)); #else pcl = &cl; #endif cls_struct_type.size = 0; cls_struct_type.alignment = 0; cls_struct_type.type = FFI_TYPE_STRUCT; cls_struct_type.elements = cls_struct_fields; struct cls_struct_3byte_1 g_dbl = { 15, 125 }; struct cls_struct_3byte_1 f_dbl = { 9, 19 }; struct cls_struct_3byte_1 res_dbl; cls_struct_fields[0] = &ffi_type_uchar; cls_struct_fields[1] = &ffi_type_ushort; cls_struct_fields[2] = NULL; dbl_arg_types[0] = &cls_struct_type; dbl_arg_types[1] = &cls_struct_type; dbl_arg_types[2] = NULL; CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type, dbl_arg_types) == FFI_OK); args_dbl[0] = &g_dbl; args_dbl[1] = &f_dbl; args_dbl[2] = NULL; ffi_call(&cif, FFI_FN(cls_struct_3byte_fn1), &res_dbl, args_dbl); /* { dg-output "15 125 9 19: 24 144" } */ printf("res: %d %d\n", res_dbl.a, res_dbl.b); /* { dg-output "\nres: 24 144" } */ CHECK(ffi_prep_closure(pcl, &cif, cls_struct_3byte_gn1, NULL) == FFI_OK); res_dbl = ((cls_struct_3byte_1(*)(cls_struct_3byte_1, cls_struct_3byte_1))(pcl))(g_dbl, f_dbl); /* { dg-output "\n15 125 9 19: 24 144" } */ printf("res: %d %d\n", res_dbl.a, res_dbl.b); /* { dg-output "\nres: 24 144" } */ exit(0); }
ffi_status ffi_prep_closure_loc(ffi_closure* closure, ffi_cif* cif, void (*fun)(ffi_cif*, void*, void**, void*), void* user_data, void* code) { ffi_status retval = ffi_prep_closure(closure, cif, fun, user_data); if (retval == FFI_OK) { mprotect(closure, sizeof(ffi_closure), PROT_READ | PROT_EXEC); } return retval; }
int main (void) { ffi_cif cif; static ffi_closure cl; ffi_closure *pcl = &cl; void* args_dbl[5]; ffi_type* cls_struct_fields[5]; ffi_type cls_struct_type; ffi_type* dbl_arg_types[5]; cls_struct_type.size = 0; cls_struct_type.alignment = 0; cls_struct_type.type = FFI_TYPE_STRUCT; cls_struct_type.elements = cls_struct_fields; struct cls_struct_4_1byte g_dbl = { 12, 13, 14, 15 }; struct cls_struct_4_1byte f_dbl = { 178, 179, 180, 181 }; struct cls_struct_4_1byte res_dbl; cls_struct_fields[0] = &ffi_type_uchar; cls_struct_fields[1] = &ffi_type_uchar; cls_struct_fields[2] = &ffi_type_uchar; cls_struct_fields[3] = &ffi_type_uchar; cls_struct_fields[4] = NULL; dbl_arg_types[0] = &cls_struct_type; dbl_arg_types[1] = &cls_struct_type; dbl_arg_types[2] = NULL; CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type, dbl_arg_types) == FFI_OK); args_dbl[0] = &g_dbl; args_dbl[1] = &f_dbl; args_dbl[2] = NULL; ffi_call(&cif, FFI_FN(cls_struct_4_1byte_fn), &res_dbl, args_dbl); /* { dg-output "12 13 14 15 178 179 180 181: 190 192 194 196" } */ CHECK( res_dbl.a == (g_dbl.a + f_dbl.a)); CHECK( res_dbl.b == (g_dbl.b + f_dbl.b)); CHECK( res_dbl.c == (g_dbl.c + f_dbl.c)); CHECK( res_dbl.d == (g_dbl.d + f_dbl.d)); CHECK(ffi_prep_closure(pcl, &cif, cls_struct_4_1byte_gn, NULL) == FFI_OK); res_dbl = ((cls_struct_4_1byte(*)(cls_struct_4_1byte, cls_struct_4_1byte))(pcl))(g_dbl, f_dbl); /* { dg-output "\n12 13 14 15 178 179 180 181: 190 192 194 196" } */ CHECK( res_dbl.a == (g_dbl.a + f_dbl.a)); CHECK( res_dbl.b == (g_dbl.b + f_dbl.b)); CHECK( res_dbl.c == (g_dbl.c + f_dbl.c)); CHECK( res_dbl.d == (g_dbl.d + f_dbl.d)); exit(0); }
int main (void) { ffi_cif cif; #ifndef USING_MMAP static ffi_closure cl; #endif ffi_closure *pcl; void * args_dbl[5]; ffi_type * cl_arg_types[5]; ffi_arg res_call; signed char a, c; signed short b, d, res_closure; #ifdef USING_MMAP pcl = allocate_mmap (sizeof(ffi_closure)); #else pcl = &cl; #endif a = 1; b = 32765; c = 127; d = -128; args_dbl[0] = &a; args_dbl[1] = &b; args_dbl[2] = &c; args_dbl[3] = &d; args_dbl[4] = NULL; cl_arg_types[0] = &ffi_type_schar; cl_arg_types[1] = &ffi_type_sshort; cl_arg_types[2] = &ffi_type_schar; cl_arg_types[3] = &ffi_type_sshort; cl_arg_types[4] = NULL; /* Initialize the cif */ CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 4, &ffi_type_sshort, cl_arg_types) == FFI_OK); ffi_call(&cif, FFI_FN(test_func_fn), &res_call, args_dbl); /* { dg-output "1 32765 127 -128: 32765" } */ printf("res: %d\n", res_call); /* { dg-output "\nres: 32765" } */ CHECK(ffi_prep_closure(pcl, &cif, test_func_gn, NULL) == FFI_OK); res_closure = (*((test_type)pcl))(1, 32765, 127, -128); /* { dg-output "\n1 32765 127 -128: 32765" } */ printf("res: %d\n", res_closure); /* { dg-output "\nres: 32765" } */ exit(0); }
int main(void) { ffi_type* my_ffi_struct_fields[4]; ffi_type my_ffi_struct_type; ffi_cif cif; static ffi_closure cl; ffi_closure *pcl = &cl; void* args[4]; ffi_type* arg_types[3]; struct my_ffi_struct g = { 1.0, 2.0, 3.0 }; struct my_ffi_struct f = { 1.0, 2.0, 3.0 }; struct my_ffi_struct res; my_ffi_struct_type.size = 0; my_ffi_struct_type.alignment = 0; my_ffi_struct_type.type = FFI_TYPE_STRUCT; my_ffi_struct_type.elements = my_ffi_struct_fields; my_ffi_struct_fields[0] = &ffi_type_double; my_ffi_struct_fields[1] = &ffi_type_double; my_ffi_struct_fields[2] = &ffi_type_double; my_ffi_struct_fields[3] = NULL; arg_types[0] = &my_ffi_struct_type; arg_types[1] = &my_ffi_struct_type; arg_types[2] = NULL; CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &my_ffi_struct_type, arg_types) == FFI_OK); args[0] = &g; args[1] = &f; args[2] = NULL; ffi_call(&cif, FFI_FN(callee), &res, args); /* { dg-output "1 2 3 1 2 3: 2 4 6" } */ CHECK(res.a == 2.0); CHECK(res.b == 4.0); CHECK(res.c == 6.0); CHECK(ffi_prep_closure(pcl, &cif, stub, NULL) == FFI_OK); res = ((my_ffi_struct(*)(struct my_ffi_struct, struct my_ffi_struct))(pcl))(g, f); /* { dg-output "\n1 2 3 1 2 3: 2 4 6" } */ CHECK(res.a == 2.0); CHECK(res.b == 4.0); CHECK(res.c == 6.0); exit(0);; }
// "Leaky" in that it exists for lifetime of program, // kind of unavoidable though. static ffi_closure *seed_make_rl_closure(SeedObject function) { ffi_cif *cif; ffi_closure *closure; cif = g_new0(ffi_cif, 1); closure = mmap(0, sizeof(ffi_closure), PROT_READ | PROT_WRITE | PROT_EXEC, MAP_ANON | MAP_PRIVATE, -1, 0); ffi_prep_cif(cif, FFI_DEFAULT_ABI, 0, &ffi_type_sint, 0); ffi_prep_closure(closure, cif, seed_handle_rl_closure, function); return closure; }
static bool callback_prep(void* ctx, void* code, Closure* closure, char* errmsg, size_t errmsgsize) { FunctionType* fnInfo = (FunctionType *) ctx; ffi_status ffiStatus; ffiStatus = ffi_prep_closure(code, &fnInfo->ffi_cif, callback_invoke, closure); if (ffiStatus != FFI_OK) { snprintf(errmsg, errmsgsize, "ffi_prep_closure failed. status=%#x", ffiStatus); return false; } return true; }
int main (void) { ffi_cif cif; #ifndef USING_MMAP static ffi_closure cl; #endif ffi_closure *pcl; ffi_type * cl_arg_types[17]; int res; #ifdef USING_MMAP pcl = allocate_mmap (sizeof(ffi_closure)); #else pcl = &cl; #endif cl_arg_types[0] = &ffi_type_uint64; cl_arg_types[1] = &ffi_type_uint; cl_arg_types[2] = &ffi_type_uint64; cl_arg_types[3] = &ffi_type_uint; cl_arg_types[4] = &ffi_type_sshort; cl_arg_types[5] = &ffi_type_uint64; cl_arg_types[6] = &ffi_type_uint; cl_arg_types[7] = &ffi_type_uint; cl_arg_types[8] = &ffi_type_double; cl_arg_types[9] = &ffi_type_uint; cl_arg_types[10] = &ffi_type_uint; cl_arg_types[11] = &ffi_type_float; cl_arg_types[12] = &ffi_type_uint; cl_arg_types[13] = &ffi_type_uint; cl_arg_types[14] = &ffi_type_uint; cl_arg_types[15] = &ffi_type_uint; cl_arg_types[16] = NULL; /* Initialize the cif */ CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 16, &ffi_type_sint, cl_arg_types) == FFI_OK); CHECK(ffi_prep_closure(pcl, &cif, closure_test_fn0, (void *) 3 /* userdata */) == FFI_OK); res = (*((closure_test_type0)pcl)) (1LL, 2, 3LL, 4, 127, 429LL, 7, 8, 9.5, 10, 11, 12, 13, 19, 21, 1); /* { dg-output "1 2 3 4 127 429 7 8 9 10 11 12 13 19 21 1 3: 680" } */ printf("res: %d\n",res); /* { dg-output "\nres: 680" } */ exit(0); }
int main (void) { ffi_cif cif; #ifndef USING_MMAP static ffi_closure cl; #endif ffi_closure *pcl; ffi_type * cl_arg_types[17]; int res; #ifdef USING_MMAP pcl = allocate_mmap (sizeof(ffi_closure)); #else pcl = &cl; #endif cl_arg_types[0] = &ffi_type_float; cl_arg_types[1] = &ffi_type_float; cl_arg_types[2] = &ffi_type_float; cl_arg_types[3] = &ffi_type_float; cl_arg_types[4] = &ffi_type_float; cl_arg_types[5] = &ffi_type_float; cl_arg_types[6] = &ffi_type_float; cl_arg_types[7] = &ffi_type_float; cl_arg_types[8] = &ffi_type_double; cl_arg_types[9] = &ffi_type_uint; cl_arg_types[10] = &ffi_type_float; cl_arg_types[11] = &ffi_type_float; cl_arg_types[12] = &ffi_type_uint; cl_arg_types[13] = &ffi_type_float; cl_arg_types[14] = &ffi_type_float; cl_arg_types[15] = &ffi_type_uint; cl_arg_types[16] = NULL; /* Initialize the cif */ CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 16, &ffi_type_sint, cl_arg_types) == FFI_OK); CHECK(ffi_prep_closure(pcl, &cif, closure_test_fn3, (void *) 3 /* userdata */) == FFI_OK); res = (*((closure_test_type3)pcl)) (1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8, 9, 10, 11.11, 12.0, 13, 19.19, 21.21, 1); /* { dg-output "1 2 3 4 5 6 7 8 9 10 11 12 13 19 21 1 3: 135" } */ printf("res: %d\n",res); /* { dg-output "\nres: 135" } */ exit(0); }
int main (void) { ffi_cif cif; static ffi_closure cl; ffi_closure *pcl = &cl; void* args_dbl[5]; ffi_type* cls_struct_fields[4]; ffi_type cls_struct_type; ffi_type* dbl_arg_types[5]; cls_struct_type.size = 0; cls_struct_type.alignment = 0; cls_struct_type.type = FFI_TYPE_STRUCT; cls_struct_type.elements = cls_struct_fields; struct cls_struct_3byte g_dbl = { 12, 119 }; struct cls_struct_3byte f_dbl = { 1, 15 }; struct cls_struct_3byte res_dbl; cls_struct_fields[0] = &ffi_type_ushort; cls_struct_fields[1] = &ffi_type_uchar; cls_struct_fields[2] = NULL; dbl_arg_types[0] = &cls_struct_type; dbl_arg_types[1] = &cls_struct_type; dbl_arg_types[2] = NULL; CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type, dbl_arg_types) == FFI_OK); args_dbl[0] = &g_dbl; args_dbl[1] = &f_dbl; args_dbl[2] = NULL; ffi_call(&cif, FFI_FN(cls_struct_3byte_fn), &res_dbl, args_dbl); /* { dg-output "12 119 1 15: 13 134" } */ CHECK( res_dbl.a == (g_dbl.a + f_dbl.a)); CHECK( res_dbl.b == (g_dbl.b + f_dbl.b)); CHECK(ffi_prep_closure(pcl, &cif, cls_struct_3byte_gn, NULL) == FFI_OK); res_dbl = ((cls_struct_3byte(*)(cls_struct_3byte, cls_struct_3byte))(pcl))(g_dbl, f_dbl); /* { dg-output "\n12 119 1 15: 13 134" } */ CHECK( res_dbl.a == (g_dbl.a + f_dbl.a)); CHECK( res_dbl.b == (g_dbl.b + f_dbl.b)); exit(0); }
void* createAdjustor (int cconv, StgStablePtr hptr, StgFunPtr wptr, char *typeString) { ffi_cif *cif; ffi_type **arg_types; nat n_args, i; ffi_type *result_type; ffi_closure *cl; int r, abi; void *code; n_args = strlen(typeString) - 1; cif = stgMallocBytes(sizeof(ffi_cif), "createAdjustor"); arg_types = stgMallocBytes(n_args * sizeof(ffi_type*), "createAdjustor"); result_type = char_to_ffi_type(typeString[0]); for (i=0; i < n_args; i++) { arg_types[i] = char_to_ffi_type(typeString[i+1]); } switch (cconv) { #if defined(mingw32_HOST_OS) && defined(i386_HOST_ARCH) case 0: /* stdcall */ abi = FFI_STDCALL; break; #endif case 1: /* ccall */ abi = FFI_DEFAULT_ABI; break; default: barf("createAdjustor: convention %d not supported on this platform", cconv); } r = ffi_prep_cif(cif, abi, n_args, result_type, arg_types); if (r != FFI_OK) barf("ffi_prep_cif failed: %d", r); cl = allocateExec(sizeof(ffi_closure), &code); if (cl == NULL) { barf("createAdjustor: failed to allocate memory"); } r = ffi_prep_closure(cl, cif, (void*)wptr, hptr/*userdata*/); if (r != FFI_OK) barf("ffi_prep_closure failed: %d", r); return (void*)code; }
static bool prep_trampoline(void* ctx, void* code, Closure* closure, char* errmsg, size_t errmsgsize) { ffi_status ffiStatus; #if defined(USE_RAW) ffiStatus = ffi_prep_raw_closure(code, &mh_cif, attached_method_invoke, closure); #else ffiStatus = ffi_prep_closure(code, &mh_cif, attached_method_invoke, closure); #endif if (ffiStatus != FFI_OK) { snprintf(errmsg, errmsgsize, "ffi_prep_closure failed. status=%#x", ffiStatus); return false; } return true; }
ffi_status ffi_prep_java_raw_closure (ffi_raw_closure* cl, ffi_cif *cif, void (*fun)(ffi_cif*,void*,ffi_raw*,void*), void *user_data) { ffi_status status; status = ffi_prep_closure ((ffi_closure*) cl, cif, &ffi_java_translate_args, (void*)cl); if (status == FFI_OK) { cl->fun = fun; cl->user_data = user_data; } return status; }
int main (void) { ffi_cif cif; static ffi_closure cl; ffi_closure *pcl = &cl; ffi_type * cl_arg_types[2]; cl_arg_types[0] = &ffi_type_ushort; cl_arg_types[1] = NULL; /* Initialize the cif */ CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, &ffi_type_ushort, cl_arg_types) == FFI_OK); CHECK(ffi_prep_closure(pcl, &cif, cls_ret_ushort_fn, NULL) == FFI_OK); (*((cls_ret_ushort)pcl))(65535); /* { dg-output "65535: 65535" } */ exit(0); }
static int alien_callback_new(lua_State *L) { int fn_ref; alien_Callback *ac; ffi_closure **ud; ffi_status status; ffi_abi abi; luaL_checktype(L, 1, LUA_TFUNCTION); ac = (alien_Callback *)malloc(sizeof(alien_Callback)); ud = (ffi_closure **)lua_newuserdata(L, sizeof(ffi_closure**)); if(ac != NULL && ud != NULL) { int j; *ud = malloc_closure(); if(*ud == NULL) { free(ac); luaL_error(L, "alien: cannot allocate callback"); } ac->L = L; ac->ret_type = AT_VOID; ac->ffi_ret_type = &ffi_type_void; abi = FFI_DEFAULT_ABI; ac->nparams = 0; ac->params = NULL; ac->ffi_params = NULL; lua_pushvalue(L, 1); ac->fn_ref = lua_ref(L, 1); luaL_getmetatable(L, ALIEN_CALLBACK_META); lua_setmetatable(L, -2); status = ffi_prep_cif(&(ac->cif), abi, ac->nparams, ac->ffi_ret_type, ac->ffi_params); if(status != FFI_OK) luaL_error(L, "alien: cannot create callback"); status = ffi_prep_closure(*ud, &(ac->cif), &alien_callback_call, ac); ac->fn = *ud; ac->lib = NULL; ac->name = NULL; if(status != FFI_OK) luaL_error(L, "alien: cannot create callback"); return 1; } else { if(ac) free(ac); luaL_error(L, "alien: cannot allocate callback"); } return 0; }
int main (void) { ffi_cif cif; static ffi_closure cl; ffi_closure *pcl = &cl; ffi_type * cl_arg_types[17]; cl_arg_types[0] = &ffi_type_float; cl_arg_types[1] = &ffi_type_float; cl_arg_types[2] = &ffi_type_float; cl_arg_types[3] = &ffi_type_float; cl_arg_types[4] = &ffi_type_sshort; cl_arg_types[5] = &ffi_type_float; cl_arg_types[6] = &ffi_type_float; cl_arg_types[7] = &ffi_type_uint; cl_arg_types[8] = &ffi_type_double; cl_arg_types[9] = &ffi_type_uint; cl_arg_types[10] = &ffi_type_uint; cl_arg_types[11] = &ffi_type_float; cl_arg_types[12] = &ffi_type_uint; cl_arg_types[13] = &ffi_type_uint; cl_arg_types[14] = &ffi_type_uint; cl_arg_types[15] = &ffi_type_uint; cl_arg_types[16] = NULL; /* Initialize the cif */ CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 16, &ffi_type_sint, cl_arg_types) == FFI_OK); CHECK(ffi_prep_closure(pcl, &cif, closure_test_fn1, (void *) 3 /* userdata */) == FFI_OK); (*((closure_test_type1)pcl)) (1.1, 2.2, 3.3, 4.4, 127, 5.5, 6.6, 8, 9, 10, 11, 12.0, 13, 19, 21, 1); /* { dg-output "1 2 3 4 127 5 6 8 9 10 11 12 13 19 21 1 3: 255" } */ exit(0); }
int main (void) { ffi_cif cif; #ifndef USING_MMAP static ffi_closure cl; #endif ffi_closure *pcl; ffi_type * cl_arg_types[17]; int i, res; #ifdef USING_MMAP pcl = allocate_mmap (sizeof(ffi_closure)); #else pcl = &cl; #endif for (i = 0; i < 15; i++) { cl_arg_types[i] = &ffi_type_uint64; } cl_arg_types[15] = &ffi_type_uint; cl_arg_types[16] = NULL; /* Initialize the cif */ CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 16, &ffi_type_sint, cl_arg_types) == FFI_OK); CHECK(ffi_prep_closure(pcl, &cif, closure_test_fn0, (void *) 3 /* userdata */) == FFI_OK); res = (*((closure_test_type0)pcl)) (1LL, 2LL, 3LL, 4LL, 127LL, 429LL, 7LL, 8LL, 9LL, 10LL, 11LL, 12LL, 13LL, 19LL, 21LL, 1); /* { dg-output "1 2 3 4 127 429 7 8 9 10 11 12 13 19 21 1 3: 680" } */ printf("res: %d\n",res); /* { dg-output "\nres: 680" } */ exit(0); }
int main (void) { ffi_cif cif; #ifndef USING_MMAP static ffi_closure cl; #endif ffi_closure *pcl; ffi_type * cl_arg_types[3]; int i, res; #ifdef USING_MMAP pcl = allocate_mmap (sizeof(ffi_closure)); #else //pcl = &cl; pcl = malloc(sizeof(*pcl)); #endif cl_arg_types[0] = &ffi_type_pointer; cl_arg_types[1] = &ffi_type_pointer; cl_arg_types[2] = &ffi_type_pointer; /* Initialize the cif */ CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 3, &ffi_type_sint, cl_arg_types) == FFI_OK); CHECK(ffi_prep_closure(pcl, &cif, closure_test_fn7, (void *) 99 /* userdata */) == FFI_OK); base_func(4, 5, 6); /* { dg-output "4 5 6\n" } */ (*((closure_test_type7)pcl))((void*)1, (void*)2, (void*)3); /* { dg-output "1 2 3\n" } */ exit(0); }
int main (void) { ffi_cif cif; #ifndef USING_MMAP static ffi_closure cl; #endif ffi_closure *pcl; void* args_dbl[5]; ffi_type* cls_struct_fields[10]; ffi_type cls_struct_type; ffi_type* dbl_arg_types[5]; #ifdef USING_MMAP pcl = allocate_mmap (sizeof(ffi_closure)); #else pcl = &cl; #endif cls_struct_type.size = 0; cls_struct_type.alignment = 0; cls_struct_type.type = FFI_TYPE_STRUCT; cls_struct_type.elements = cls_struct_fields; struct_72byte e_dbl = { 9.0, 2.0, 6.0, 5.0, 3.0, 4.0, 8.0, 1.0, 7 }; struct_72byte f_dbl = { 1.0, 2.0, 3.0, 7.0, 2.0, 5.0, 6.0, 7.0, 4 }; struct_72byte g_dbl = { 4.0, 5.0, 7.0, 9.0, 1.0, 1.0, 2.0, 9.0, 3 }; struct_72byte h_dbl = { 8.0, 6.0, 1.0, 4.0, 0.0, 3.0, 3.0, 1.0, 2 }; struct_72byte res_dbl; cls_struct_fields[0] = &ffi_type_double; cls_struct_fields[1] = &ffi_type_double; cls_struct_fields[2] = &ffi_type_double; cls_struct_fields[3] = &ffi_type_double; cls_struct_fields[4] = &ffi_type_double; cls_struct_fields[5] = &ffi_type_double; cls_struct_fields[6] = &ffi_type_double; cls_struct_fields[7] = &ffi_type_double; cls_struct_fields[8] = &ffi_type_sint64; cls_struct_fields[9] = NULL; dbl_arg_types[0] = &cls_struct_type; dbl_arg_types[1] = &cls_struct_type; dbl_arg_types[2] = &cls_struct_type; dbl_arg_types[3] = &cls_struct_type; dbl_arg_types[4] = NULL; CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 4, &cls_struct_type, dbl_arg_types) == FFI_OK); args_dbl[0] = &e_dbl; args_dbl[1] = &f_dbl; args_dbl[2] = &g_dbl; args_dbl[3] = &h_dbl; args_dbl[4] = NULL; ffi_call(&cif, FFI_FN(cls_struct_72byte_fn), &res_dbl, args_dbl); /* { dg-output "22 15 17 25 6 13 19 18 16" } */ printf("res: %g %g %g %g %g %g %g %g %lld\n", res_dbl.a, res_dbl.b, res_dbl.c, res_dbl.d, res_dbl.e, res_dbl.f, res_dbl.g, res_dbl.h, res_dbl.i); /* { dg-output "\nres: 22 15 17 25 6 13 19 18 16" } */ CHECK(ffi_prep_closure(pcl, &cif, cls_struct_72byte_gn, NULL) == FFI_OK); res_dbl = ((struct_72byte(*)(struct_72byte, struct_72byte, struct_72byte, struct_72byte))(pcl))(e_dbl, f_dbl, g_dbl, h_dbl); /* { dg-output "\n22 15 17 25 6 13 19 18 16" } */ printf("res: %g %g %g %g %g %g %g %g %lld\n", res_dbl.a, res_dbl.b, res_dbl.c, res_dbl.d, res_dbl.e, res_dbl.f, res_dbl.g, res_dbl.h, res_dbl.i); /* { dg-output "\nres: 22 15 17 25 6 13 19 18 16" } */ exit(0); }
int main(/*@unused@*/ int argc, /*@unused@*/ char *argv[]) { ffi_cif cif; ffi_type *args[MAX_ARGS]; void *values[MAX_ARGS]; char *s; signed char sc; unsigned char uc; signed short ss; unsigned short us; unsigned long ul; long long ll; float f; double d; long double ld; signed int si1; signed int si2; ffi_arg rint; long long rlonglong; ffi_type ts1_type; ffi_type ts2_type; ffi_type ts3_type; ffi_type ts4_type; ffi_type ts5_type; ffi_type *ts1_type_elements[4]; ffi_type *ts2_type_elements[3]; ffi_type *ts3_type_elements[2]; ffi_type *ts4_type_elements[4]; ffi_type *ts5_type_elements[3]; ts1_type.size = 0; ts1_type.alignment = 0; ts1_type.type = FFI_TYPE_STRUCT; ts2_type.size = 0; ts2_type.alignment = 0; ts2_type.type = FFI_TYPE_STRUCT; ts3_type.size = 0; ts3_type.alignment = 0; ts3_type.type = FFI_TYPE_STRUCT; ts4_type.size = 0; ts4_type.alignment = 0; ts4_type.type = FFI_TYPE_STRUCT; ts5_type.size = 0; ts5_type.alignment = 0; ts5_type.type = FFI_TYPE_STRUCT; /*@-immediatetrans@*/ ts1_type.elements = ts1_type_elements; ts2_type.elements = ts2_type_elements; ts3_type.elements = ts3_type_elements; ts4_type.elements = ts4_type_elements; ts5_type.elements = ts5_type_elements; /*@=immediatetrans@*/ ts1_type_elements[0] = &ffi_type_uchar; ts1_type_elements[1] = &ffi_type_double; ts1_type_elements[2] = &ffi_type_uint; ts1_type_elements[3] = NULL; ts2_type_elements[0] = &ffi_type_double; ts2_type_elements[1] = &ffi_type_double; ts2_type_elements[2] = NULL; ts3_type_elements[0] = &ffi_type_sint; ts3_type_elements[1] = NULL; ts4_type_elements[0] = &ffi_type_uint; ts4_type_elements[1] = &ffi_type_uint; ts4_type_elements[2] = &ffi_type_uint; ts4_type_elements[3] = NULL; ts5_type_elements[0] = &ffi_type_schar; ts5_type_elements[1] = &ffi_type_schar; ts5_type_elements[2] = NULL; ul = 0; /* return value tests */ { #if defined(MIPS) /* || defined(ARM) */ puts ("long long tests not run. This is a known bug on this architecture."); #else args[0] = &ffi_type_sint64; values[0] = ≪ /* Initialize the cif */ CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, &ffi_type_sint64, args) == FFI_OK); for (ll = 0LL; ll < 100LL; ll++) { ul++; ffi_call(&cif, FFI_FN(return_ll), &rlonglong, values); CHECK(rlonglong == ll); } for (ll = 55555555555000LL; ll < 55555555555100LL; ll++) { ul++; ffi_call(&cif, FFI_FN(return_ll), &rlonglong, values); CHECK(rlonglong == ll); } #endif args[0] = &ffi_type_schar; values[0] = ≻ /* Initialize the cif */ CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, &ffi_type_schar, args) == FFI_OK); for (sc = (signed char) -127; sc < (signed char) 127; /*@-type@*/ sc++ /*@=type@*/) { ul++; ffi_call(&cif, FFI_FN(return_sc), &rint, values); CHECK(rint == (int) sc); } args[0] = &ffi_type_uchar; values[0] = &uc; /* Initialize the cif */ CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, &ffi_type_uchar, args) == FFI_OK); for (uc = (unsigned char) '\x00'; uc < (unsigned char) '\xff'; /*@-type@*/ uc++ /*@=type@*/) { ul++; ffi_call(&cif, FFI_FN(return_uc), &rint, values); CHECK(rint == (signed int) uc); } printf("%lu return value tests run\n", ul); } #ifdef BROKEN_LONG_DOUBLE printf ("This architecture has broken `long double' support. No floating point\ntests have been run.\n"); #else /* float arg tests */ { args[0] = &ffi_type_float; values[0] = &f; /* Initialize the cif */ CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, &ffi_type_longdouble, args) == FFI_OK); f = 3.14159; #if 0 /* This is ifdef'd out for now. long double support under SunOS/gcc is pretty much non-existent. You'll get the odd bus error in library routines like printf(). */ printf ("%Lf\n", ldblit(f)); #endif ld = 666; ffi_call(&cif, FFI_FN(ldblit), &ld, values); #if 0 /* This is ifdef'd out for now. long double support under SunOS/gcc is pretty much non-existent. You'll get the odd bus error in library routines like printf(). */ printf ("%Lf, %Lf, %Lf, %Lf\n", ld, ldblit(f), ld - ldblit(f), LDBL_EPSILON); #endif /* These are not always the same!! Check for a reasonable delta */ /*@-realcompare@*/ if (ld - ldblit(f) < LDBL_EPSILON) /*@=realcompare@*/ puts("long double return value tests ok!"); else CHECK(0); } /* float arg tests */ { args[0] = &ffi_type_sint; values[0] = &si1; args[1] = &ffi_type_float; values[1] = &f; args[2] = &ffi_type_double; values[2] = &d; args[3] = &ffi_type_longdouble; values[3] = &ld; args[4] = &ffi_type_sint; values[4] = &si2; /* Initialize the cif */ CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 5, &ffi_type_sint, args) == FFI_OK); si1 = 6; f = 3.14159; d = (double)1.0/(double)3.0; ld = 2.71828182846L; si2 = 10; floating (si1, f, d, ld, si2); ffi_call(&cif, FFI_FN(floating), &rint, values); printf ("%d vs %d\n", rint, floating (si1, f, d, ld, si2)); CHECK(rint == floating(si1, f, d, ld, si2)); printf("float arg tests ok!\n"); } #endif /* strlen tests */ { args[0] = &ffi_type_pointer; values[0] = (void*) &s; /* Initialize the cif */ CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, &ffi_type_sint, args) == FFI_OK); s = "a"; ffi_call(&cif, FFI_FN(my_strlen), &rint, values); CHECK(rint == 1); s = "1234567"; ffi_call(&cif, FFI_FN(my_strlen), &rint, values); CHECK(rint == 7); s = "1234567890123456789012345"; ffi_call(&cif, FFI_FN(my_strlen), &rint, values); CHECK(rint == 25); printf("strlen tests passed\n"); } /* float arg tests */ { args[0] = &ffi_type_float; values[0] = &f; /* Initialize the cif */ CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, &ffi_type_double, args) == FFI_OK); f = 3.14159; ffi_call(&cif, FFI_FN(dblit), &d, values); /* These are not always the same!! Check for a reasonable delta */ /*@-realcompare@*/ CHECK(d - dblit(f) < DBL_EPSILON); /*@=realcompare@*/ printf("double return value tests ok!\n"); } /* many arg tests */ { float ff; float fa[13]; for (ul = 0; ul < 13; ul++) { args[ul] = &ffi_type_float; values[ul] = &fa[ul]; fa[ul] = (float) ul; } /* Initialize the cif */ CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 13, &ffi_type_float, args) == FFI_OK); /*@-usedef@*/ ff = many(fa[0], fa[1], fa[2], fa[3], fa[4], fa[5], fa[6], fa[7], fa[8], fa[9], fa[10],fa[11],fa[12]); /*@=usedef@*/ ffi_call(&cif, FFI_FN(many), &f, values); /*@-realcompare@*/ if (f - ff < FLT_EPSILON) /*@=realcompare@*/ printf("many arg tests ok!\n"); else #ifdef POWERPC printf("many arg tests failed! This is a gcc bug.\n"); #else CHECK(0); #endif } /* promotion tests */ { args[0] = &ffi_type_schar; args[1] = &ffi_type_sshort; args[2] = &ffi_type_uchar; args[3] = &ffi_type_ushort; values[0] = ≻ values[1] = &ss; values[2] = &uc; values[3] = &us; /* Initialize the cif */ CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 4, &ffi_type_sint, args) == FFI_OK); us = 0; ul = 0; for (sc = (signed char) -127; sc <= (signed char) 120; /*@-type@*/ sc += 1 /*@=type@*/) for (ss = -30000; ss <= 30000; ss += 10000) for (uc = (unsigned char) 0; uc <= (unsigned char) 200; /*@-type@*/ uc += 20 /*@=type@*/) for (us = 0; us <= 60000; us += 10000) { ul++; ffi_call(&cif, FFI_FN(promotion), &rint, values); CHECK(rint == (int) sc + (int) ss + (int) uc + (int) us); } printf("%lu promotion tests run\n", ul); } #ifndef X86_WIN32 /* Structures dont work on Win32 */ /* struct tests */ { test_structure_1 ts1_arg; /* This is a hack to get a properly aligned result buffer */ test_structure_1 *ts1_result = (test_structure_1 *) malloc (sizeof(test_structure_1)); args[0] = &ts1_type; values[0] = &ts1_arg; /* Initialize the cif */ CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, &ts1_type, args) == FFI_OK); ts1_arg.uc = '\x01'; ts1_arg.d = 3.14159; ts1_arg.ui = 555; ffi_call(&cif, FFI_FN(struct1), ts1_result, values); CHECK(ts1_result->ui == 556); CHECK(ts1_result->d == 3.14159 - 1); puts ("structure test 1 ok!\n"); free (ts1_result); } /* struct tests */ { test_structure_2 ts2_arg; /* This is a hack to get a properly aligned result buffer */ test_structure_2 *ts2_result = (test_structure_2 *) malloc (sizeof(test_structure_2)); args[0] = &ts2_type; values[0] = &ts2_arg; /* Initialize the cif */ CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, &ts2_type, args) == FFI_OK); ts2_arg.d1 = 5.55; ts2_arg.d2 = 6.66; printf ("%g\n", ts2_result->d1); printf ("%g\n", ts2_result->d2); ffi_call(&cif, FFI_FN(struct2), ts2_result, values); printf ("%g\n", ts2_result->d1); printf ("%g\n", ts2_result->d2); CHECK(ts2_result->d1 == 5.55 - 1); CHECK(ts2_result->d2 == 6.66 - 1); printf("structure test 2 ok!\n"); free (ts2_result); } /* struct tests */ { int compare_value; test_structure_3 ts3_arg; test_structure_3 *ts3_result = (test_structure_3 *) malloc (sizeof(test_structure_3)); args[0] = &ts3_type; values[0] = &ts3_arg; /* Initialize the cif */ CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, &ts3_type, args) == FFI_OK); ts3_arg.si = -123; compare_value = ts3_arg.si; ffi_call(&cif, FFI_FN(struct3), ts3_result, values); printf ("%d %d\n", ts3_result->si, -(compare_value*2)); if (ts3_result->si == -(ts3_arg.si*2)) puts ("structure test 3 ok!"); else { puts ("Structure test 3 found structure passing bug."); puts (" Current versions of GCC are not 100% compliant with the"); puts (" n32 ABI. There is a known problem related to passing"); puts (" small structures. Send a bug report to the gcc maintainers."); } free (ts3_result); } /* struct tests */ { test_structure_4 ts4_arg; /* This is a hack to get a properly aligned result buffer */ test_structure_4 *ts4_result = (test_structure_4 *) malloc (sizeof(test_structure_4)); args[0] = &ts4_type; values[0] = &ts4_arg; /* Initialize the cif */ CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, &ts4_type, args) == FFI_OK); ts4_arg.ui1 = 2; ts4_arg.ui2 = 3; ts4_arg.ui3 = 4; ffi_call (&cif, FFI_FN(struct4), ts4_result, values); if (ts4_result->ui3 == 2U * 3U * 4U) puts ("structure test 4 ok!"); else puts ("Structure test 4 found GCC's structure passing bug."); free (ts4_result); } /* struct tests */ { test_structure_5 ts5_arg1, ts5_arg2; /* This is a hack to get a properly aligned result buffer */ test_structure_5 *ts5_result = (test_structure_5 *) malloc (sizeof(test_structure_5)); args[0] = &ts5_type; args[1] = &ts5_type; values[0] = &ts5_arg1; values[1] = &ts5_arg2; /* Initialize the cif */ CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &ts5_type, args) == FFI_OK); ts5_arg1.c1 = 2; ts5_arg1.c2 = 6; ts5_arg2.c1 = 5; ts5_arg2.c2 = 3; ffi_call (&cif, FFI_FN(struct5), ts5_result, values); if (ts5_result->c1 == 7 && ts5_result->c2 == 3) puts ("structure test 5 ok!"); else puts ("Structure test 5 found GCC's structure passing bug."); free (ts5_result); } #else printf("Structure passing doesn't work on Win32.\n"); #endif /* X86_WIN32 */ # if FFI_CLOSURES /* A simple closure test */ { ffi_closure cl; ffi_type * cl_arg_types[3]; cl_arg_types[0] = &ffi_type_sint; cl_arg_types[1] = &ffi_type_float; cl_arg_types[2] = NULL; /* Initialize the cif */ CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &ffi_type_sint, cl_arg_types) == FFI_OK); CHECK(ffi_prep_closure(&cl, &cif, closure_test_fn, (void *) 3 /* userdata */) == FFI_OK); CHECK((*((closure_test_type)(&cl)))(1, 2.0) == 6); } # endif /* If we arrived here, all is good */ (void) puts("\nLooks good. No surprises.\n"); /*@-compdestroy@*/ return 0; }
int main (void) { ffi_cif cif; #ifndef USING_MMAP static ffi_closure cl; #endif ffi_closure *pcl; void* args_dbl[5]; ffi_type* cls_struct_fields[4]; ffi_type cls_struct_type; ffi_type* dbl_arg_types[5]; #ifdef USING_MMAP pcl = allocate_mmap (sizeof(ffi_closure)); #else pcl = &cl; #endif cls_struct_type.size = 0; cls_struct_type.alignment = 0; cls_struct_type.type = FFI_TYPE_STRUCT; cls_struct_type.elements = cls_struct_fields; struct cls_struct_16byte h_dbl = { 7, 8.0, 9 }; struct cls_struct_16byte j_dbl = { 1, 9.0, 3 }; struct cls_struct_16byte res_dbl; cls_struct_fields[0] = &ffi_type_uint32; cls_struct_fields[1] = &ffi_type_double; cls_struct_fields[2] = &ffi_type_uint32; cls_struct_fields[3] = NULL; dbl_arg_types[0] = &cls_struct_type; dbl_arg_types[1] = &cls_struct_type; dbl_arg_types[2] = NULL; CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type, dbl_arg_types) == FFI_OK); args_dbl[0] = &h_dbl; args_dbl[1] = &j_dbl; args_dbl[2] = NULL; ffi_call(&cif, FFI_FN(cls_struct_16byte_fn), &res_dbl, args_dbl); /* { dg-output "7 8 9 1 9 3: 8 17 12" } */ printf("res: %d %g %d\n", res_dbl.a, res_dbl.b, res_dbl.c); /* { dg-output "\nres: 8 17 12" } */ res_dbl.a = 0; res_dbl.b = 0.0; res_dbl.c = 0; CHECK(ffi_prep_closure(pcl, &cif, cls_struct_16byte_gn, NULL) == FFI_OK); res_dbl = ((cls_struct_16byte(*)(cls_struct_16byte, cls_struct_16byte))(pcl))(h_dbl, j_dbl); /* { dg-output "\n7 8 9 1 9 3: 8 17 12" } */ printf("res: %d %g %d\n", res_dbl.a, res_dbl.b, res_dbl.c); /* { dg-output "\nres: 8 17 12" } */ exit(0); }
ffi_info *AllocFunctionCallback(PyObject *callable, PyObject *converters, PyObject *restype, int is_cdecl) { int result; ffi_info *p; int nArgs, i; ffi_abi cc; nArgs = PySequence_Size(converters); p = (ffi_info *)PyMem_Malloc(sizeof(ffi_info) + sizeof(ffi_type) * (nArgs + 1)); if (p == NULL) { PyErr_NoMemory(); return NULL; } p->pcl = MallocClosure(); if (p->pcl == NULL) { PyErr_NoMemory(); goto error; } for (i = 0; i < nArgs; ++i) { PyObject *cnv = PySequence_GetItem(converters, i); if (cnv == NULL) goto error; p->atypes[i] = GetType(cnv); Py_DECREF(cnv); } p->atypes[i] = NULL; if (restype == Py_None) { p->setfunc = NULL; p->restype = &ffi_type_void; } else { StgDictObject *dict = PyType_stgdict(restype); if (dict == NULL || dict->setfunc == NULL) { PyErr_SetString(PyExc_TypeError, "invalid result type for callback function"); goto error; } p->setfunc = dict->setfunc; p->restype = &dict->ffi_type_pointer; } cc = FFI_DEFAULT_ABI; #if defined(MS_WIN32) && !defined(_WIN32_WCE) if (is_cdecl == 0) cc = FFI_STDCALL; #endif result = ffi_prep_cif(&p->cif, cc, nArgs, GetType(restype), &p->atypes[0]); if (result != FFI_OK) { PyErr_Format(PyExc_RuntimeError, "ffi_prep_cif failed with %d", result); goto error; } result = ffi_prep_closure(p->pcl, &p->cif, closure_fcn, p); if (result != FFI_OK) { PyErr_Format(PyExc_RuntimeError, "ffi_prep_closure failed with %d", result); goto error; } p->converters = converters; p->callable = callable; return p; error: if (p) { if (p->pcl) FreeClosure(p->pcl); PyMem_Free(p); } return NULL; }
CThunkObject *_ctypes_alloc_callback(PyObject *callable, PyObject *converters, PyObject *restype, int flags) { int result; CThunkObject *p; Py_ssize_t nArgs, i; ffi_abi cc; nArgs = PySequence_Size(converters); p = CThunkObject_new(nArgs); if (p == NULL) return NULL; assert(CThunk_CheckExact((PyObject *)p)); p->pcl = _ctypes_alloc_closure(); if (p->pcl == NULL) { PyErr_NoMemory(); goto error; } p->flags = flags; for (i = 0; i < nArgs; ++i) { PyObject *cnv = PySequence_GetItem(converters, i); if (cnv == NULL) goto error; p->atypes[i] = _ctypes_get_ffi_type(cnv); Py_DECREF(cnv); } p->atypes[i] = NULL; Py_INCREF(restype); p->restype = restype; if (restype == Py_None) { p->setfunc = NULL; p->ffi_restype = &ffi_type_void; } else { StgDictObject *dict = PyType_stgdict(restype); if (dict == NULL || dict->setfunc == NULL) { PyErr_SetString(PyExc_TypeError, "invalid result type for callback function"); goto error; } p->setfunc = dict->setfunc; p->ffi_restype = &dict->ffi_type_pointer; } cc = FFI_DEFAULT_ABI; #if defined(MS_WIN32) && !defined(_WIN32_WCE) && !defined(MS_WIN64) if ((flags & FUNCFLAG_CDECL) == 0) cc = FFI_STDCALL; #endif result = ffi_prep_cif(&p->cif, cc, Py_SAFE_DOWNCAST(nArgs, Py_ssize_t, int), _ctypes_get_ffi_type(restype), &p->atypes[0]); if (result != FFI_OK) { PyErr_Format(PyExc_RuntimeError, "ffi_prep_cif failed with %d", result); goto error; } result = ffi_prep_closure(p->pcl, &p->cif, closure_fcn, p); if (result != FFI_OK) { PyErr_Format(PyExc_RuntimeError, "ffi_prep_closure failed with %d", result); goto error; } Py_INCREF(converters); p->converters = converters; Py_INCREF(callable); p->callable = callable; return p; error: Py_XDECREF(p); return NULL; }