cdlopen.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382
  1. /* ffi.dlopen() interface with dlopen()/dlsym()/dlclose() */
  2. static void *cdlopen_fetch(PyObject *libname, void *libhandle, char *symbol)
  3. {
  4. void *address;
  5. if (libhandle == NULL) {
  6. PyErr_Format(FFIError, "library '%s' has been closed",
  7. PyText_AS_UTF8(libname));
  8. return NULL;
  9. }
  10. dlerror(); /* clear error condition */
  11. address = dlsym(libhandle, symbol);
  12. if (address == NULL) {
  13. const char *error = dlerror();
  14. PyErr_Format(FFIError, "symbol '%s' not found in library '%s': %s",
  15. symbol, PyText_AS_UTF8(libname), error);
  16. }
  17. return address;
  18. }
  19. static void cdlopen_close_ignore_errors(void *libhandle)
  20. {
  21. if (libhandle != NULL)
  22. dlclose(libhandle);
  23. }
  24. static int cdlopen_close(PyObject *libname, void *libhandle)
  25. {
  26. if (libhandle != NULL && dlclose(libhandle) != 0) {
  27. const char *error = dlerror();
  28. PyErr_Format(FFIError, "closing library '%s': %s",
  29. PyText_AS_UTF8(libname), error);
  30. return -1;
  31. }
  32. return 0;
  33. }
  34. static PyObject *ffi_dlopen(PyObject *self, PyObject *args)
  35. {
  36. char *filename_or_null, *printable_filename;
  37. void *handle;
  38. int flags = 0;
  39. if (PyTuple_GET_SIZE(args) == 0 || PyTuple_GET_ITEM(args, 0) == Py_None) {
  40. PyObject *dummy;
  41. if (!PyArg_ParseTuple(args, "|Oi:load_library",
  42. &dummy, &flags))
  43. return NULL;
  44. filename_or_null = NULL;
  45. }
  46. else if (!PyArg_ParseTuple(args, "et|i:load_library",
  47. Py_FileSystemDefaultEncoding, &filename_or_null,
  48. &flags))
  49. return NULL;
  50. if ((flags & (RTLD_NOW | RTLD_LAZY)) == 0)
  51. flags |= RTLD_NOW;
  52. printable_filename = filename_or_null ? filename_or_null : "<None>";
  53. handle = dlopen(filename_or_null, flags);
  54. if (handle == NULL) {
  55. const char *error = dlerror();
  56. PyErr_Format(PyExc_OSError, "cannot load library '%s': %s",
  57. printable_filename, error);
  58. return NULL;
  59. }
  60. return (PyObject *)lib_internal_new((FFIObject *)self,
  61. printable_filename, handle);
  62. }
  63. static PyObject *ffi_dlclose(PyObject *self, PyObject *args)
  64. {
  65. LibObject *lib;
  66. void *libhandle;
  67. if (!PyArg_ParseTuple(args, "O!", &Lib_Type, &lib))
  68. return NULL;
  69. libhandle = lib->l_libhandle;
  70. lib->l_libhandle = NULL;
  71. if (libhandle == NULL) {
  72. PyErr_Format(FFIError, "library '%s' is already closed "
  73. "or was not created with ffi.dlopen()",
  74. PyText_AS_UTF8(lib->l_libname));
  75. return NULL;
  76. }
  77. /* Clear the dict to force further accesses to do cdlopen_fetch()
  78. again, and fail because the library was closed. */
  79. PyDict_Clear(lib->l_dict);
  80. if (cdlopen_close(lib->l_libname, libhandle) < 0)
  81. return NULL;
  82. Py_INCREF(Py_None);
  83. return Py_None;
  84. }
  85. static Py_ssize_t cdl_4bytes(char *src)
  86. {
  87. /* read 4 bytes in little-endian order; return it as a signed integer */
  88. signed char *ssrc = (signed char *)src;
  89. unsigned char *usrc = (unsigned char *)src;
  90. return (ssrc[0] << 24) | (usrc[1] << 16) | (usrc[2] << 8) | usrc[3];
  91. }
  92. static _cffi_opcode_t cdl_opcode(char *src)
  93. {
  94. return (_cffi_opcode_t)cdl_4bytes(src);
  95. }
  96. typedef struct {
  97. unsigned long long value;
  98. int neg;
  99. } cdl_intconst_t;
  100. static int _cdl_realize_global_int(struct _cffi_getconst_s *gc)
  101. {
  102. /* The 'address' field of 'struct _cffi_global_s' is set to point
  103. to this function in case ffiobj_init() sees constant integers.
  104. This fishes around after the 'ctx->globals' array, which is
  105. initialized to contain another array, this time of
  106. 'cdl_intconst_t' structures. We get the nth one and it tells
  107. us what to return.
  108. */
  109. cdl_intconst_t *ic;
  110. ic = (cdl_intconst_t *)(gc->ctx->globals + gc->ctx->num_globals);
  111. ic += gc->gindex;
  112. gc->value = ic->value;
  113. return ic->neg;
  114. }
  115. static int ffiobj_init(PyObject *self, PyObject *args, PyObject *kwds)
  116. {
  117. FFIObject *ffi;
  118. static char *keywords[] = {"module_name", "_version", "_types",
  119. "_globals", "_struct_unions", "_enums",
  120. "_typenames", "_includes", NULL};
  121. char *ffiname = "?", *types = NULL, *building = NULL;
  122. Py_ssize_t version = -1;
  123. Py_ssize_t types_len = 0;
  124. PyObject *globals = NULL, *struct_unions = NULL, *enums = NULL;
  125. PyObject *typenames = NULL, *includes = NULL;
  126. if (!PyArg_ParseTupleAndKeywords(args, kwds,
  127. "|sns#O!O!O!O!O!:FFI", keywords,
  128. &ffiname, &version, &types, &types_len,
  129. &PyTuple_Type, &globals,
  130. &PyTuple_Type, &struct_unions,
  131. &PyTuple_Type, &enums,
  132. &PyTuple_Type, &typenames,
  133. &PyTuple_Type, &includes))
  134. return -1;
  135. ffi = (FFIObject *)self;
  136. if (ffi->ctx_is_nonempty) {
  137. PyErr_SetString(PyExc_ValueError,
  138. "cannot call FFI.__init__() more than once");
  139. return -1;
  140. }
  141. ffi->ctx_is_nonempty = 1;
  142. if (version == -1 && types_len == 0)
  143. return 0;
  144. if (version < CFFI_VERSION_MIN || version > CFFI_VERSION_MAX) {
  145. PyErr_Format(PyExc_ImportError,
  146. "cffi out-of-line Python module '%s' has unknown "
  147. "version %p", ffiname, (void *)version);
  148. return -1;
  149. }
  150. if (types_len > 0) {
  151. /* unpack a string of 4-byte entries into an array of _cffi_opcode_t */
  152. _cffi_opcode_t *ntypes;
  153. Py_ssize_t i, n = types_len / 4;
  154. building = PyMem_Malloc(n * sizeof(_cffi_opcode_t));
  155. if (building == NULL)
  156. goto error;
  157. ntypes = (_cffi_opcode_t *)building;
  158. for (i = 0; i < n; i++) {
  159. ntypes[i] = cdl_opcode(types);
  160. types += 4;
  161. }
  162. ffi->types_builder.ctx.types = ntypes;
  163. ffi->types_builder.ctx.num_types = n;
  164. building = NULL;
  165. }
  166. if (globals != NULL) {
  167. /* unpack a tuple alternating strings and ints, each two together
  168. describing one global_s entry with no specified address or size.
  169. The int is only used with integer constants. */
  170. struct _cffi_global_s *nglobs;
  171. cdl_intconst_t *nintconsts;
  172. Py_ssize_t i, n = PyTuple_GET_SIZE(globals) / 2;
  173. i = n * (sizeof(struct _cffi_global_s) + sizeof(cdl_intconst_t));
  174. building = PyMem_Malloc(i);
  175. if (building == NULL)
  176. goto error;
  177. memset(building, 0, i);
  178. nglobs = (struct _cffi_global_s *)building;
  179. nintconsts = (cdl_intconst_t *)(nglobs + n);
  180. for (i = 0; i < n; i++) {
  181. char *g = PyBytes_AS_STRING(PyTuple_GET_ITEM(globals, i * 2));
  182. nglobs[i].type_op = cdl_opcode(g); g += 4;
  183. nglobs[i].name = g;
  184. if (_CFFI_GETOP(nglobs[i].type_op) == _CFFI_OP_CONSTANT_INT ||
  185. _CFFI_GETOP(nglobs[i].type_op) == _CFFI_OP_ENUM) {
  186. PyObject *o = PyTuple_GET_ITEM(globals, i * 2 + 1);
  187. nglobs[i].address = &_cdl_realize_global_int;
  188. #if PY_MAJOR_VERSION < 3
  189. if (PyInt_Check(o)) {
  190. nintconsts[i].neg = PyInt_AS_LONG(o) <= 0;
  191. nintconsts[i].value = (long long)PyInt_AS_LONG(o);
  192. }
  193. else
  194. #endif
  195. {
  196. nintconsts[i].neg = PyObject_RichCompareBool(o, Py_False,
  197. Py_LE);
  198. nintconsts[i].value = PyLong_AsUnsignedLongLongMask(o);
  199. if (PyErr_Occurred())
  200. goto error;
  201. }
  202. }
  203. }
  204. ffi->types_builder.ctx.globals = nglobs;
  205. ffi->types_builder.ctx.num_globals = n;
  206. building = NULL;
  207. }
  208. if (struct_unions != NULL) {
  209. /* unpack a tuple of struct/unions, each described as a sub-tuple;
  210. the item 0 of each sub-tuple describes the struct/union, and
  211. the items 1..N-1 describe the fields, if any */
  212. struct _cffi_struct_union_s *nstructs;
  213. struct _cffi_field_s *nfields;
  214. Py_ssize_t i, n = PyTuple_GET_SIZE(struct_unions);
  215. Py_ssize_t nf = 0; /* total number of fields */
  216. for (i = 0; i < n; i++) {
  217. nf += PyTuple_GET_SIZE(PyTuple_GET_ITEM(struct_unions, i)) - 1;
  218. }
  219. i = (n * sizeof(struct _cffi_struct_union_s) +
  220. nf * sizeof(struct _cffi_field_s));
  221. building = PyMem_Malloc(i);
  222. if (building == NULL)
  223. goto error;
  224. memset(building, 0, i);
  225. nstructs = (struct _cffi_struct_union_s *)building;
  226. nfields = (struct _cffi_field_s *)(nstructs + n);
  227. nf = 0;
  228. for (i = 0; i < n; i++) {
  229. /* 'desc' is the tuple of strings (desc_struct, desc_field_1, ..) */
  230. PyObject *desc = PyTuple_GET_ITEM(struct_unions, i);
  231. Py_ssize_t j, nf1 = PyTuple_GET_SIZE(desc) - 1;
  232. char *s = PyBytes_AS_STRING(PyTuple_GET_ITEM(desc, 0));
  233. /* 's' is the first string, describing the struct/union */
  234. nstructs[i].type_index = cdl_4bytes(s); s += 4;
  235. nstructs[i].flags = cdl_4bytes(s); s += 4;
  236. nstructs[i].name = s;
  237. if (nstructs[i].flags & (_CFFI_F_OPAQUE | _CFFI_F_EXTERNAL)) {
  238. nstructs[i].size = (size_t)-1;
  239. nstructs[i].alignment = -1;
  240. nstructs[i].first_field_index = -1;
  241. nstructs[i].num_fields = 0;
  242. assert(nf1 == 0);
  243. }
  244. else {
  245. nstructs[i].size = (size_t)-2;
  246. nstructs[i].alignment = -2;
  247. nstructs[i].first_field_index = nf;
  248. nstructs[i].num_fields = nf1;
  249. }
  250. for (j = 0; j < nf1; j++) {
  251. char *f = PyBytes_AS_STRING(PyTuple_GET_ITEM(desc, j + 1));
  252. /* 'f' is one of the other strings beyond the first one,
  253. describing one field each */
  254. nfields[nf].field_type_op = cdl_opcode(f); f += 4;
  255. nfields[nf].field_offset = (size_t)-1;
  256. if (_CFFI_GETOP(nfields[nf].field_type_op) != _CFFI_OP_NOOP) {
  257. nfields[nf].field_size = cdl_4bytes(f); f += 4;
  258. }
  259. else {
  260. nfields[nf].field_size = (size_t)-1;
  261. }
  262. nfields[nf].name = f;
  263. nf++;
  264. }
  265. }
  266. ffi->types_builder.ctx.struct_unions = nstructs;
  267. ffi->types_builder.ctx.fields = nfields;
  268. ffi->types_builder.ctx.num_struct_unions = n;
  269. building = NULL;
  270. }
  271. if (enums != NULL) {
  272. /* unpack a tuple of strings, each of which describes one enum_s
  273. entry */
  274. struct _cffi_enum_s *nenums;
  275. Py_ssize_t i, n = PyTuple_GET_SIZE(enums);
  276. i = n * sizeof(struct _cffi_enum_s);
  277. building = PyMem_Malloc(i);
  278. if (building == NULL)
  279. goto error;
  280. memset(building, 0, i);
  281. nenums = (struct _cffi_enum_s *)building;
  282. for (i = 0; i < n; i++) {
  283. char *e = PyBytes_AS_STRING(PyTuple_GET_ITEM(enums, i));
  284. /* 'e' is a string describing the enum */
  285. nenums[i].type_index = cdl_4bytes(e); e += 4;
  286. nenums[i].type_prim = cdl_4bytes(e); e += 4;
  287. nenums[i].name = e; e += strlen(e) + 1;
  288. nenums[i].enumerators = e;
  289. }
  290. ffi->types_builder.ctx.enums = nenums;
  291. ffi->types_builder.ctx.num_enums = n;
  292. building = NULL;
  293. }
  294. if (typenames != NULL) {
  295. /* unpack a tuple of strings, each of which describes one typename_s
  296. entry */
  297. struct _cffi_typename_s *ntypenames;
  298. Py_ssize_t i, n = PyTuple_GET_SIZE(typenames);
  299. i = n * sizeof(struct _cffi_typename_s);
  300. building = PyMem_Malloc(i);
  301. if (building == NULL)
  302. goto error;
  303. memset(building, 0, i);
  304. ntypenames = (struct _cffi_typename_s *)building;
  305. for (i = 0; i < n; i++) {
  306. char *t = PyBytes_AS_STRING(PyTuple_GET_ITEM(typenames, i));
  307. /* 't' is a string describing the typename */
  308. ntypenames[i].type_index = cdl_4bytes(t); t += 4;
  309. ntypenames[i].name = t;
  310. }
  311. ffi->types_builder.ctx.typenames = ntypenames;
  312. ffi->types_builder.ctx.num_typenames = n;
  313. building = NULL;
  314. }
  315. if (includes != NULL) {
  316. PyObject *included_libs;
  317. included_libs = PyTuple_New(PyTuple_GET_SIZE(includes));
  318. if (included_libs == NULL)
  319. return -1;
  320. Py_INCREF(includes);
  321. ffi->types_builder.included_ffis = includes;
  322. ffi->types_builder.included_libs = included_libs;
  323. }
  324. /* Above, we took directly some "char *" strings out of the strings,
  325. typically from somewhere inside tuples. Keep them alive by
  326. incref'ing the whole input arguments. */
  327. Py_INCREF(args);
  328. Py_XINCREF(kwds);
  329. ffi->types_builder._keepalive1 = args;
  330. ffi->types_builder._keepalive2 = kwds;
  331. return 0;
  332. error:
  333. if (building != NULL)
  334. PyMem_Free(building);
  335. if (!PyErr_Occurred())
  336. PyErr_NoMemory();
  337. return -1;
  338. }