+ struct psi_ffi_struct_info *info = darg->engine.info;
+
+ if (info) {
+ darg->engine.info = NULL;
+ darg->engine.type = NULL;
+
+ psi_plist_free(info->eles);
+ pefree(info, 1);
+ }
+}
+
+static void psi_ffi_extvar_get(ffi_cif *sig, void *result, void **args, void *data) {
+ struct psi_decl_extvar *evar = data;
+
+ psi_decl_extvar_get(evar, result);
+}
+
+static void psi_ffi_extvar_set(ffi_cif *sig, void *result, void **args, void *data) {
+ struct psi_decl_extvar *evar = data;
+
+ psi_decl_extvar_set(evar, args[0]);
+}
+
+static bool psi_ffi_decl_init(struct psi_context *, struct psi_decl *);
+
+static bool psi_ffi_extvar_init(struct psi_context *C,
+ struct psi_decl_extvar *evar)
+{
+ struct psi_ffi_extvar_info *info = pecalloc(1, sizeof(*info), 1);
+ ffi_status rc;
+
+ evar->info = info;
+
+ psi_ffi_decl_init(C, evar->getter);
+ psi_ffi_decl_init(C, evar->setter);
+
+ rc = ffi_prep_cif(&info->get.signature, FFI_DEFAULT_ABI, 0,
+ psi_context_decl_arg_call_type(C, evar->getter->func), NULL);
+ if (FFI_OK != rc) {
+ return false;
+ }
+ rc = psi_ffi_prep_closure(&info->get.closure, &info->get.code,
+ &info->get.signature, psi_ffi_extvar_get, evar);
+ if (FFI_OK != rc) {
+ return false;
+ }
+
+ info->set.params[0] = psi_context_decl_arg_call_type(C, evar->arg);
+ rc = ffi_prep_cif(&info->set.signature, FFI_DEFAULT_ABI, 1,
+ &ffi_type_void, info->set.params);
+ if (FFI_OK != rc) {
+ return false;
+ }
+ rc = psi_ffi_prep_closure(&info->set.closure, &info->set.code,
+ &info->set.signature, psi_ffi_extvar_set, evar);
+ if (FFI_OK != rc) {
+ return false;
+ }
+
+ evar->getter->sym = info->get.code;
+ evar->setter->sym = info->set.code;
+
+ return true;