static PyObject *ffi_dlclose(PyObject *self, PyObject *args) { LibObject *lib; void *libhandle; if (!PyArg_ParseTuple(args, "O!", &Lib_Type, &lib)) return NULL; libhandle = lib->l_libhandle; lib->l_libhandle = NULL; if (libhandle == NULL) { PyErr_Format(FFIError, "library '%s' is already closed " "or was not created with ffi.dlopen()", PyText_AS_UTF8(lib->l_libname)); return NULL; } /* Clear the dict to force further accesses to do cdlopen_fetch() again, and fail because the library was closed. */ PyDict_Clear(lib->l_dict); if (cdlopen_close(lib->l_libname, libhandle) < 0) return NULL; Py_INCREF(Py_None); return Py_None; }
static void *cdlopen_fetch(PyObject *libname, void *libhandle, char *symbol) { void *address; if (libhandle == NULL) { PyErr_Format(FFIError, "library '%s' has been closed", PyText_AS_UTF8(libname)); return NULL; } dlerror(); /* clear error condition */ address = dlsym(libhandle, symbol); if (address == NULL) { const char *error = dlerror(); PyErr_Format(FFIError, "symbol '%s' not found in library '%s': %s", symbol, PyText_AS_UTF8(libname), error); } return address; }
static int cdlopen_close(PyObject *libname, void *libhandle) { if (libhandle != NULL && dlclose(libhandle) != 0) { const char *error = dlerror(); PyErr_Format(FFIError, "closing library '%s': %s", PyText_AS_UTF8(libname), error); return -1; } return 0; }
static CTypeDescrObject *_ffi_type(FFIObject *ffi, PyObject *arg, int accept) { /* Returns the CTypeDescrObject from the user-supplied 'arg'. Does not return a new reference! */ if ((accept & ACCEPT_STRING) && PyText_Check(arg)) { PyObject *types_dict = ffi->types_builder.types_dict; PyObject *x = PyDict_GetItem(types_dict, arg); if (x == NULL) { char *input_text = PyText_AS_UTF8(arg); int err, index = parse_c_type(&ffi->info, input_text); if (index < 0) return _ffi_bad_type(ffi, input_text); x = realize_c_type_or_func(&ffi->types_builder, ffi->info.output, index); if (x == NULL) return NULL; /* Cache under the name given by 'arg', in addition to the fact that the same ct is probably already cached under its standardized name. In a few cases, it is not, e.g. if it is a primitive; for the purpose of this function, the important point is the following line, which makes sure that in any case the next _ffi_type() with the same 'arg' will succeed early, in PyDict_GetItem() above. */ err = PyDict_SetItem(types_dict, arg, x); Py_DECREF(x); /* we know it was written in types_dict (unless out of mem), so there is at least that ref left */ if (err < 0) return NULL; } if (CTypeDescr_Check(x)) return (CTypeDescrObject *)x; else if (accept & CONSIDER_FN_AS_FNPTR) return unwrap_fn_as_fnptr(x); else return unexpected_fn_type(x); } else if ((accept & ACCEPT_CTYPE) && CTypeDescr_Check(arg)) { return (CTypeDescrObject *)arg; } else if ((accept & ACCEPT_CDATA) && CData_Check(arg)) { return ((CDataObject *)arg)->c_type; } #if PY_MAJOR_VERSION < 3 else if (PyUnicode_Check(arg)) { CTypeDescrObject *result; arg = PyUnicode_AsASCIIString(arg); if (arg == NULL) return NULL; result = _ffi_type(ffi, arg, accept); Py_DECREF(arg); return result; } #endif else { const char *m1 = (accept & ACCEPT_STRING) ? "string" : ""; const char *m2 = (accept & ACCEPT_CTYPE) ? "ctype object" : ""; const char *m3 = (accept & ACCEPT_CDATA) ? "cdata object" : ""; const char *s12 = (*m1 && (*m2 || *m3)) ? " or " : ""; const char *s23 = (*m2 && *m3) ? " or " : ""; PyErr_Format(PyExc_TypeError, "expected a %s%s%s%s%s, got '%.200s'", m1, s12, m2, s23, m3, Py_TYPE(arg)->tp_name); return NULL; } }