file_emulator.h 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. /* Emulation of PyFile_Check() and PyFile_AsFile() for Python 3. */
  2. static PyObject *PyIOBase_TypeObj;
  3. static int init_file_emulator(void)
  4. {
  5. if (PyIOBase_TypeObj == NULL) {
  6. PyObject *io = PyImport_ImportModule("_io");
  7. if (io == NULL)
  8. return -1;
  9. PyIOBase_TypeObj = PyObject_GetAttrString(io, "_IOBase");
  10. if (PyIOBase_TypeObj == NULL)
  11. return -1;
  12. }
  13. return 0;
  14. }
  15. #define PyFile_Check(p) PyObject_IsInstance(p, PyIOBase_TypeObj)
  16. static void _close_file_capsule(PyObject *ob_capsule)
  17. {
  18. FILE *f = (FILE *)PyCapsule_GetPointer(ob_capsule, "FILE");
  19. if (f != NULL)
  20. fclose(f);
  21. }
  22. static FILE *PyFile_AsFile(PyObject *ob_file)
  23. {
  24. PyObject *ob, *ob_capsule = NULL, *ob_mode = NULL;
  25. FILE *f;
  26. int fd;
  27. const char *mode;
  28. ob = PyObject_CallMethod(ob_file, "flush", NULL);
  29. if (ob == NULL)
  30. goto fail;
  31. Py_DECREF(ob);
  32. ob_capsule = PyObject_GetAttrString(ob_file, "__cffi_FILE");
  33. if (ob_capsule == NULL) {
  34. PyErr_Clear();
  35. fd = PyObject_AsFileDescriptor(ob_file);
  36. if (fd < 0)
  37. goto fail;
  38. ob_mode = PyObject_GetAttrString(ob_file, "mode");
  39. if (ob_mode == NULL)
  40. goto fail;
  41. mode = PyText_AsUTF8(ob_mode);
  42. if (mode == NULL)
  43. goto fail;
  44. fd = dup(fd);
  45. if (fd < 0) {
  46. PyErr_SetFromErrno(PyExc_OSError);
  47. goto fail;
  48. }
  49. f = fdopen(fd, mode);
  50. if (f == NULL) {
  51. close(fd);
  52. PyErr_SetFromErrno(PyExc_OSError);
  53. goto fail;
  54. }
  55. setbuf(f, NULL); /* non-buffered */
  56. Py_DECREF(ob_mode);
  57. ob_mode = NULL;
  58. ob_capsule = PyCapsule_New(f, "FILE", _close_file_capsule);
  59. if (ob_capsule == NULL) {
  60. fclose(f);
  61. goto fail;
  62. }
  63. if (PyObject_SetAttrString(ob_file, "__cffi_FILE", ob_capsule) < 0)
  64. goto fail;
  65. }
  66. else {
  67. f = PyCapsule_GetPointer(ob_capsule, "FILE");
  68. }
  69. Py_DECREF(ob_capsule); /* assumes still at least one reference */
  70. return f;
  71. fail:
  72. Py_XDECREF(ob_mode);
  73. Py_XDECREF(ob_capsule);
  74. return NULL;
  75. }