+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]);
+}
+
+struct psi_ffi_extvar_info {
+ struct {
+ ffi_cif signature;
+ void *code;
+ ffi_closure *closure;
+ } get;
+ struct {
+ ffi_cif signature;
+ ffi_type *params[1];
+ void *code;
+ ffi_closure *closure;
+ } set;
+};
+
+static inline ffi_status psi_ffi_extvar_init(struct psi_decl_extvar *evar) {
+ struct psi_ffi_extvar_info *info = calloc(1, sizeof(*info));
+ ffi_type *type;
+ ffi_status rc;
+
+ evar->info = info;
+
+ psi_ffi_decl_init(evar->getter);
+ psi_ffi_decl_init(evar->setter);
+
+ type = psi_ffi_decl_arg_type(evar->arg, evar->getter);
+
+ rc = ffi_prep_cif(&info->get.signature, FFI_DEFAULT_ABI, 0,
+ type, NULL);
+ if (FFI_OK != rc) {
+ return rc;
+ }
+ rc = psi_ffi_prep_closure(&info->get.closure, &info->get.code,
+ &info->get.signature, psi_ffi_extvar_get, evar);
+ if (FFI_OK != rc) {
+ return rc;
+ }
+
+ info->set.params[0] = type;
+ rc = ffi_prep_cif(&info->set.signature, FFI_DEFAULT_ABI, 1,
+ &ffi_type_void, info->set.params);
+ if (FFI_OK != rc) {
+ return rc;
+ }
+ rc = psi_ffi_prep_closure(&info->set.closure, &info->set.code,
+ &info->set.signature, psi_ffi_extvar_set, evar);
+ if (FFI_OK != rc) {
+ return rc;
+ }
+
+ evar->getter->sym = info->get.code;
+ evar->setter->sym = info->set.code;
+
+ return FFI_OK;
+}
+
+static inline void psi_ffi_extvar_dtor(struct psi_decl_extvar *evar) {
+ if (evar->info) {
+ free(evar->info);
+ evar->info = NULL;
+ }
+}
+
+static inline struct psi_ffi_context *psi_ffi_context_init(struct psi_ffi_context *L) {
+ ffi_status rc;
+
+ if (!L) {
+ L = malloc(sizeof(*L));
+ }
+ memset(L, 0, sizeof(*L));
+
+ L->params[0] = &ffi_type_pointer;
+ L->params[1] = &ffi_type_pointer;
+ rc = ffi_prep_cif(&L->signature, FFI_DEFAULT_ABI, 2, &ffi_type_void, L->params);
+ assert(rc == FFI_OK);
+
+ return L;
+}
+
+static inline void psi_ffi_context_free(struct psi_ffi_context **L) {
+ if (*L) {
+ free(*L);
+ *L = NULL;
+ }
+}
+
+static void psi_ffi_init(struct psi_context *C)
+{
+ C->context = psi_ffi_context_init(NULL);
+}
+
+static void psi_ffi_dtor(struct psi_context *C)
+{
+ if (C->decls) {
+ size_t i = 0;
+ struct psi_decl *decl;
+
+ while (psi_plist_get(C->decls, i++, &decl)) {
+ psi_ffi_decl_dtor(decl);