| typedef void *(*gs_fetch_addr_fn)(void); | |
| typedef struct { | |
| PyObject_HEAD | |
| PyObject *gs_name; | |
| CTypeDescrObject *gs_type; | |
| char *gs_data; | |
| gs_fetch_addr_fn gs_fetch_addr; | |
| } GlobSupportObject; | |
| static void glob_support_dealloc(GlobSupportObject *gs) | |
| { | |
| Py_DECREF(gs->gs_name); | |
| Py_DECREF(gs->gs_type); | |
| PyObject_Del(gs); | |
| } | |
| static PyTypeObject GlobSupport_Type = { | |
| PyVarObject_HEAD_INIT(NULL, 0) | |
| "FFIGlobSupport", | |
| sizeof(GlobSupportObject), | |
| 0, | |
| (destructor)glob_support_dealloc, /* tp_dealloc */ | |
| 0, /* tp_print */ | |
| 0, /* tp_getattr */ | |
| 0, /* tp_setattr */ | |
| 0, /* tp_compare */ | |
| 0, /* tp_repr */ | |
| 0, /* tp_as_number */ | |
| 0, /* tp_as_sequence */ | |
| 0, /* tp_as_mapping */ | |
| 0, /* tp_hash */ | |
| 0, /* tp_call */ | |
| 0, /* tp_str */ | |
| PyObject_GenericGetAttr, /* tp_getattro */ | |
| 0, /* tp_setattro */ | |
| 0, /* tp_as_buffer */ | |
| Py_TPFLAGS_DEFAULT, /* tp_flags */ | |
| }; | |
| #define GlobSupport_Check(ob) (Py_TYPE(ob) == &GlobSupport_Type) | |
| static PyObject *make_global_var(PyObject *name, CTypeDescrObject *type, | |
| char *addr, gs_fetch_addr_fn fetch_addr) | |
| { | |
| GlobSupportObject *gs = PyObject_New(GlobSupportObject, &GlobSupport_Type); | |
| if (gs == NULL) | |
| return NULL; | |
| Py_INCREF(name); | |
| Py_INCREF(type); | |
| gs->gs_name = name; | |
| gs->gs_type = type; | |
| gs->gs_data = addr; | |
| gs->gs_fetch_addr = fetch_addr; | |
| return (PyObject *)gs; | |
| } | |
| static void *fetch_global_var_addr(GlobSupportObject *gs) | |
| { | |
| void *data; | |
| if (gs->gs_data != NULL) { | |
| data = gs->gs_data; | |
| } | |
| else { | |
| Py_BEGIN_ALLOW_THREADS | |
| restore_errno(); | |
| data = gs->gs_fetch_addr(); | |
| save_errno(); | |
| Py_END_ALLOW_THREADS | |
| } | |
| if (data == NULL) { | |
| PyErr_Format(FFIError, "global variable '%s' is at address NULL", | |
| PyText_AS_UTF8(gs->gs_name)); | |
| return NULL; | |
| } | |
| return data; | |
| } | |
| static PyObject *read_global_var(GlobSupportObject *gs) | |
| { | |
| void *data = fetch_global_var_addr(gs); | |
| if (data == NULL) | |
| return NULL; | |
| return convert_to_object(data, gs->gs_type); | |
| } | |
| static int write_global_var(GlobSupportObject *gs, PyObject *obj) | |
| { | |
| void *data = fetch_global_var_addr(gs); | |
| if (data == NULL) | |
| return -1; | |
| return convert_from_object(data, gs->gs_type, obj); | |
| } | |
| static PyObject *cg_addressof_global_var(GlobSupportObject *gs) | |
| { | |
| void *data; | |
| PyObject *x, *ptrtype = new_pointer_type(gs->gs_type); | |
| if (ptrtype == NULL) | |
| return NULL; | |
| data = fetch_global_var_addr(gs); | |
| if (data != NULL) | |
| x = new_simple_cdata(data, (CTypeDescrObject *)ptrtype); | |
| else | |
| x = NULL; | |
| Py_DECREF(ptrtype); | |
| return x; | |
| } |