+
+static inline struct psi_ffi_call *psi_ffi_call_alloc(struct psi_context *C, decl *decl) {
+ int rc;
+ size_t i, c = decl->args ? decl->args->count : 0;
+ struct psi_ffi_call *call = calloc(1, sizeof(*call) + 2 * c * sizeof(void *));
+
+ for (i = 0; i < c; ++i) {
+ call->params[i] = psi_ffi_decl_arg_type(decl->args->args[i]);
+ }
+ call->params[c] = NULL;
+
+ decl->call.info = call;
+ decl->call.rval = &decl->func->ptr;
+ decl->call.argc = c;
+ decl->call.args = (void **) &call->params[c+1];
+
+ rc = ffi_prep_cif(&call->signature, psi_ffi_abi(decl->abi->convention),
+ c, psi_ffi_decl_arg_type(decl->func), (ffi_type **) call->params);
+ ZEND_ASSERT(FFI_OK == rc);
+
+ return call;
+}
+
+static inline ffi_status psi_ffi_call_init_closure(struct psi_context *C, struct psi_ffi_call *call, impl *impl) {
+ struct psi_ffi_context *context = C->context;
+
+ return psi_ffi_prep_closure(&call->closure, &call->code, &context->signature, psi_ffi_handler, impl);
+}
+
+static inline ffi_status psi_ffi_call_init_callback_closure(struct psi_context *C, struct psi_ffi_call *call, let_callback *cb) {
+ return psi_ffi_prep_closure(&call->closure, &call->code, &call->signature, psi_ffi_callback, cb);
+}
+
+static inline void psi_ffi_call_free(struct psi_ffi_call *call) {
+ if (call->closure) {
+ psi_ffi_closure_free(call->closure);
+ }
+ free(call);
+}
+
+static inline ffi_type *psi_ffi_token_type(token_t t) {