(root)/
Python-3.12.0/
Modules/
_ctypes/
callbacks.c
       1  #ifndef Py_BUILD_CORE_BUILTIN
       2  #  define Py_BUILD_CORE_MODULE 1
       3  #endif
       4  
       5  #include "Python.h"
       6  // windows.h must be included before pycore internal headers
       7  #ifdef MS_WIN32
       8  #  include <windows.h>
       9  #endif
      10  
      11  #include "pycore_call.h"            // _PyObject_CallNoArgs()
      12  #include "pycore_runtime.h"         // _PyRuntime
      13  #include "pycore_global_objects.h"  // _Py_ID()
      14  
      15  #include <stdbool.h>
      16  
      17  #ifdef MS_WIN32
      18  #  include <malloc.h>
      19  #endif
      20  
      21  #include <ffi.h>
      22  #include "ctypes.h"
      23  
      24  #ifdef HAVE_ALLOCA_H
      25  /* AIX needs alloca.h for alloca() */
      26  #include <alloca.h>
      27  #endif
      28  
      29  /**************************************************************/
      30  
      31  static int
      32  CThunkObject_traverse(PyObject *myself, visitproc visit, void *arg)
      33  {
      34      CThunkObject *self = (CThunkObject *)myself;
      35      Py_VISIT(Py_TYPE(self));
      36      Py_VISIT(self->converters);
      37      Py_VISIT(self->callable);
      38      Py_VISIT(self->restype);
      39      return 0;
      40  }
      41  
      42  static int
      43  CThunkObject_clear(PyObject *myself)
      44  {
      45      CThunkObject *self = (CThunkObject *)myself;
      46      Py_CLEAR(self->converters);
      47      Py_CLEAR(self->callable);
      48      Py_CLEAR(self->restype);
      49      return 0;
      50  }
      51  
      52  static void
      53  CThunkObject_dealloc(PyObject *myself)
      54  {
      55      CThunkObject *self = (CThunkObject *)myself;
      56      PyTypeObject *tp = Py_TYPE(myself);
      57      PyObject_GC_UnTrack(self);
      58      (void)CThunkObject_clear(myself);
      59      if (self->pcl_write) {
      60          Py_ffi_closure_free(self->pcl_write);
      61      }
      62      PyObject_GC_Del(self);
      63      Py_DECREF(tp);
      64  }
      65  
      66  static PyType_Slot cthunk_slots[] = {
      67      {Py_tp_doc, (void *)PyDoc_STR("CThunkObject")},
      68      {Py_tp_dealloc, CThunkObject_dealloc},
      69      {Py_tp_traverse, CThunkObject_traverse},
      70      {Py_tp_clear, CThunkObject_clear},
      71      {0, NULL},
      72  };
      73  
      74  PyType_Spec cthunk_spec = {
      75      .name = "_ctypes.CThunkObject",
      76      .basicsize = sizeof(CThunkObject),
      77      .itemsize = sizeof(ffi_type),
      78      .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
      79                Py_TPFLAGS_IMMUTABLETYPE | Py_TPFLAGS_DISALLOW_INSTANTIATION),
      80      .slots = cthunk_slots,
      81  };
      82  
      83  /**************************************************************/
      84  
      85  static void
      86  PrintError(const char *msg, ...)
      87  {
      88      char buf[512];
      89      PyObject *f = PySys_GetObject("stderr");
      90      va_list marker;
      91  
      92      va_start(marker, msg);
      93      PyOS_vsnprintf(buf, sizeof(buf), msg, marker);
      94      va_end(marker);
      95      if (f != NULL && f != Py_None)
      96          PyFile_WriteString(buf, f);
      97      PyErr_Print();
      98  }
      99  
     100  
     101  #ifdef MS_WIN32
     102  /*
     103   * We must call AddRef() on non-NULL COM pointers we receive as arguments
     104   * to callback functions - these functions are COM method implementations.
     105   * The Python instances we create have a __del__ method which calls Release().
     106   *
     107   * The presence of a class attribute named '_needs_com_addref_' triggers this
     108   * behaviour.  It would also be possible to call the AddRef() Python method,
     109   * after checking for PyObject_IsTrue(), but this would probably be somewhat
     110   * slower.
     111   */
     112  static void
     113  TryAddRef(StgDictObject *dict, CDataObject *obj)
     114  {
     115      IUnknown *punk;
     116      int r = PyDict_Contains((PyObject *)dict, &_Py_ID(_needs_com_addref_));
     117      if (r <= 0) {
     118          if (r < 0) {
     119              PrintError("getting _needs_com_addref_");
     120          }
     121          return;
     122      }
     123  
     124      punk = *(IUnknown **)obj->b_ptr;
     125      if (punk)
     126          punk->lpVtbl->AddRef(punk);
     127      return;
     128  }
     129  #endif
     130  
     131  /******************************************************************************
     132   *
     133   * Call the python object with all arguments
     134   *
     135   */
     136  static void _CallPythonObject(void *mem,
     137                                ffi_type *restype,
     138                                SETFUNC setfunc,
     139                                PyObject *callable,
     140                                PyObject *converters,
     141                                int flags,
     142                                void **pArgs)
     143  {
     144      PyObject *result = NULL;
     145      Py_ssize_t i = 0, j = 0, nargs = 0;
     146      PyObject *error_object = NULL;
     147      int *space;
     148      PyGILState_STATE state = PyGILState_Ensure();
     149  
     150      assert(PyTuple_Check(converters));
     151      nargs = PyTuple_GET_SIZE(converters);
     152      assert(nargs <= CTYPES_MAX_ARGCOUNT);
     153      PyObject **args = alloca(nargs * sizeof(PyObject *));
     154      PyObject **cnvs = PySequence_Fast_ITEMS(converters);
     155      for (i = 0; i < nargs; i++) {
     156          PyObject *cnv = cnvs[i]; // borrowed ref
     157          StgDictObject *dict;
     158          dict = PyType_stgdict(cnv);
     159  
     160          if (dict && dict->getfunc && !_ctypes_simple_instance(cnv)) {
     161              PyObject *v = dict->getfunc(*pArgs, dict->size);
     162              if (!v) {
     163                  PrintError("create argument %zd:\n", i);
     164                  goto Done;
     165              }
     166              args[i] = v;
     167              /* XXX XXX XX
     168                 We have the problem that c_byte or c_short have dict->size of
     169                 1 resp. 4, but these parameters are pushed as sizeof(int) bytes.
     170                 BTW, the same problem occurs when they are pushed as parameters
     171              */
     172          } else if (dict) {
     173              /* Hm, shouldn't we use PyCData_AtAddress() or something like that instead? */
     174              CDataObject *obj = (CDataObject *)_PyObject_CallNoArgs(cnv);
     175              if (!obj) {
     176                  PrintError("create argument %zd:\n", i);
     177                  goto Done;
     178              }
     179              if (!CDataObject_Check(obj)) {
     180                  Py_DECREF(obj);
     181                  PrintError("unexpected result of create argument %zd:\n", i);
     182                  goto Done;
     183              }
     184              memcpy(obj->b_ptr, *pArgs, dict->size);
     185              args[i] = (PyObject *)obj;
     186  #ifdef MS_WIN32
     187              TryAddRef(dict, obj);
     188  #endif
     189          } else {
     190              PyErr_SetString(PyExc_TypeError,
     191                              "cannot build parameter");
     192              PrintError("Parsing argument %zd\n", i);
     193              goto Done;
     194          }
     195          /* XXX error handling! */
     196          pArgs++;
     197      }
     198  
     199      if (flags & (FUNCFLAG_USE_ERRNO | FUNCFLAG_USE_LASTERROR)) {
     200          error_object = _ctypes_get_errobj(&space);
     201          if (error_object == NULL)
     202              goto Done;
     203          if (flags & FUNCFLAG_USE_ERRNO) {
     204              int temp = space[0];
     205              space[0] = errno;
     206              errno = temp;
     207          }
     208  #ifdef MS_WIN32
     209          if (flags & FUNCFLAG_USE_LASTERROR) {
     210              int temp = space[1];
     211              space[1] = GetLastError();
     212              SetLastError(temp);
     213          }
     214  #endif
     215      }
     216  
     217      result = PyObject_Vectorcall(callable, args, nargs, NULL);
     218      if (result == NULL) {
     219          _PyErr_WriteUnraisableMsg("on calling ctypes callback function",
     220                                    callable);
     221      }
     222  
     223  #ifdef MS_WIN32
     224      if (flags & FUNCFLAG_USE_LASTERROR) {
     225          int temp = space[1];
     226          space[1] = GetLastError();
     227          SetLastError(temp);
     228      }
     229  #endif
     230      if (flags & FUNCFLAG_USE_ERRNO) {
     231          int temp = space[0];
     232          space[0] = errno;
     233          errno = temp;
     234      }
     235      Py_XDECREF(error_object);
     236  
     237      if (restype != &ffi_type_void && result) {
     238          assert(setfunc);
     239  
     240  #ifdef WORDS_BIGENDIAN
     241          /* See the corresponding code in _ctypes_callproc():
     242             in callproc.c, around line 1219. */
     243          if (restype->type != FFI_TYPE_FLOAT && restype->size < sizeof(ffi_arg)) {
     244              mem = (char *)mem + sizeof(ffi_arg) - restype->size;
     245          }
     246  #endif
     247  
     248          /* keep is an object we have to keep alive so that the result
     249             stays valid.  If there is no such object, the setfunc will
     250             have returned Py_None.
     251  
     252             If there is such an object, we have no choice than to keep
     253             it alive forever - but a refcount and/or memory leak will
     254             be the result.  EXCEPT when restype is py_object - Python
     255             itself knows how to manage the refcount of these objects.
     256          */
     257          PyObject *keep = setfunc(mem, result, 0);
     258  
     259          if (keep == NULL) {
     260              /* Could not convert callback result. */
     261              _PyErr_WriteUnraisableMsg("on converting result "
     262                                        "of ctypes callback function",
     263                                        callable);
     264          }
     265          else if (setfunc != _ctypes_get_fielddesc("O")->setfunc) {
     266              if (keep == Py_None) {
     267                  /* Nothing to keep */
     268                  Py_DECREF(keep);
     269              }
     270              else if (PyErr_WarnEx(PyExc_RuntimeWarning,
     271                                    "memory leak in callback function.",
     272                                    1) == -1) {
     273                  _PyErr_WriteUnraisableMsg("on converting result "
     274                                            "of ctypes callback function",
     275                                            callable);
     276              }
     277          }
     278      }
     279  
     280      Py_XDECREF(result);
     281  
     282    Done:
     283      for (j = 0; j < i; j++) {
     284          Py_DECREF(args[j]);
     285      }
     286      PyGILState_Release(state);
     287  }
     288  
     289  static void closure_fcn(ffi_cif *cif,
     290                          void *resp,
     291                          void **args,
     292                          void *userdata)
     293  {
     294      CThunkObject *p = (CThunkObject *)userdata;
     295  
     296      _CallPythonObject(resp,
     297                        p->ffi_restype,
     298                        p->setfunc,
     299                        p->callable,
     300                        p->converters,
     301                        p->flags,
     302                        args);
     303  }
     304  
     305  static CThunkObject* CThunkObject_new(Py_ssize_t nargs)
     306  {
     307      CThunkObject *p;
     308      Py_ssize_t i;
     309  
     310      ctypes_state *st = GLOBAL_STATE();
     311      p = PyObject_GC_NewVar(CThunkObject, st->PyCThunk_Type, nargs);
     312      if (p == NULL) {
     313          return NULL;
     314      }
     315  
     316      p->pcl_write = NULL;
     317      p->pcl_exec = NULL;
     318      memset(&p->cif, 0, sizeof(p->cif));
     319      p->flags = 0;
     320      p->converters = NULL;
     321      p->callable = NULL;
     322      p->restype = NULL;
     323      p->setfunc = NULL;
     324      p->ffi_restype = NULL;
     325  
     326      for (i = 0; i < nargs + 1; ++i)
     327          p->atypes[i] = NULL;
     328      PyObject_GC_Track((PyObject *)p);
     329      return p;
     330  }
     331  
     332  CThunkObject *_ctypes_alloc_callback(PyObject *callable,
     333                                      PyObject *converters,
     334                                      PyObject *restype,
     335                                      int flags)
     336  {
     337      int result;
     338      CThunkObject *p;
     339      Py_ssize_t nargs, i;
     340      ffi_abi cc;
     341  
     342      assert(PyTuple_Check(converters));
     343      nargs = PyTuple_GET_SIZE(converters);
     344      p = CThunkObject_new(nargs);
     345      if (p == NULL)
     346          return NULL;
     347  
     348  #ifdef Py_DEBUG
     349      ctypes_state *st = GLOBAL_STATE();
     350      assert(CThunk_CheckExact(st, (PyObject *)p));
     351  #endif
     352  
     353      p->pcl_write = Py_ffi_closure_alloc(sizeof(ffi_closure), &p->pcl_exec);
     354      if (p->pcl_write == NULL) {
     355          PyErr_NoMemory();
     356          goto error;
     357      }
     358  
     359      p->flags = flags;
     360      PyObject **cnvs = PySequence_Fast_ITEMS(converters);
     361      for (i = 0; i < nargs; ++i) {
     362          PyObject *cnv = cnvs[i]; // borrowed ref
     363          p->atypes[i] = _ctypes_get_ffi_type(cnv);
     364      }
     365      p->atypes[i] = NULL;
     366  
     367      p->restype = Py_NewRef(restype);
     368      if (restype == Py_None) {
     369          p->setfunc = NULL;
     370          p->ffi_restype = &ffi_type_void;
     371      } else {
     372          StgDictObject *dict = PyType_stgdict(restype);
     373          if (dict == NULL || dict->setfunc == NULL) {
     374            PyErr_SetString(PyExc_TypeError,
     375                            "invalid result type for callback function");
     376            goto error;
     377          }
     378          p->setfunc = dict->setfunc;
     379          p->ffi_restype = &dict->ffi_type_pointer;
     380      }
     381  
     382      cc = FFI_DEFAULT_ABI;
     383  #if defined(MS_WIN32) && !defined(_WIN32_WCE) && !defined(MS_WIN64) && !defined(_M_ARM)
     384      if ((flags & FUNCFLAG_CDECL) == 0)
     385          cc = FFI_STDCALL;
     386  #endif
     387      result = ffi_prep_cif(&p->cif, cc,
     388                            Py_SAFE_DOWNCAST(nargs, Py_ssize_t, int),
     389                            p->ffi_restype,
     390                            &p->atypes[0]);
     391      if (result != FFI_OK) {
     392          PyErr_Format(PyExc_RuntimeError,
     393                       "ffi_prep_cif failed with %d", result);
     394          goto error;
     395      }
     396  
     397  
     398  #if HAVE_FFI_PREP_CLOSURE_LOC
     399  #   ifdef USING_APPLE_OS_LIBFFI
     400  #    ifdef HAVE_BUILTIN_AVAILABLE
     401  #      define HAVE_FFI_PREP_CLOSURE_LOC_RUNTIME __builtin_available(macos 10.15, ios 13, watchos 6, tvos 13, *)
     402  #    else
     403  #      define HAVE_FFI_PREP_CLOSURE_LOC_RUNTIME (ffi_prep_closure_loc != NULL)
     404  #    endif
     405  #   else
     406  #      define HAVE_FFI_PREP_CLOSURE_LOC_RUNTIME 1
     407  #   endif
     408      if (HAVE_FFI_PREP_CLOSURE_LOC_RUNTIME) {
     409          result = ffi_prep_closure_loc(p->pcl_write, &p->cif, closure_fcn,
     410                                      p,
     411                                      p->pcl_exec);
     412      } else
     413  #endif
     414      {
     415  #if defined(USING_APPLE_OS_LIBFFI) && defined(__arm64__)
     416          PyErr_Format(PyExc_NotImplementedError, "ffi_prep_closure_loc() is missing");
     417          goto error;
     418  #else
     419  #if defined(__clang__)
     420          #pragma clang diagnostic push
     421          #pragma clang diagnostic ignored "-Wdeprecated-declarations"
     422  #endif
     423  #if defined(__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5)))
     424          #pragma GCC diagnostic push
     425          #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
     426  #endif
     427          result = ffi_prep_closure(p->pcl_write, &p->cif, closure_fcn, p);
     428  
     429  #if defined(__clang__)
     430          #pragma clang diagnostic pop
     431  #endif
     432  #if defined(__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5)))
     433          #pragma GCC diagnostic pop
     434  #endif
     435  
     436  #endif
     437      }
     438      if (result != FFI_OK) {
     439          PyErr_Format(PyExc_RuntimeError,
     440                       "ffi_prep_closure failed with %d", result);
     441          goto error;
     442      }
     443  
     444      p->converters = Py_NewRef(converters);
     445      p->callable = Py_NewRef(callable);
     446      return p;
     447  
     448    error:
     449      Py_XDECREF(p);
     450      return NULL;
     451  }
     452  
     453  #ifdef MS_WIN32
     454  
     455  static void LoadPython(void)
     456  {
     457      if (!Py_IsInitialized()) {
     458          Py_Initialize();
     459      }
     460  }
     461  
     462  /******************************************************************/
     463  
     464  long Call_GetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv)
     465  {
     466      PyObject *func, *result;
     467      long retval;
     468      static PyObject *context;
     469  
     470      if (context == NULL)
     471          context = PyUnicode_InternFromString("_ctypes.DllGetClassObject");
     472  
     473      func = _PyImport_GetModuleAttrString("ctypes", "DllGetClassObject");
     474      if (!func) {
     475          PyErr_WriteUnraisable(context ? context : Py_None);
     476          /* There has been a warning before about this already */
     477          return E_FAIL;
     478      }
     479  
     480      {
     481          PyObject *py_rclsid = PyLong_FromVoidPtr((void *)rclsid);
     482          if (py_rclsid == NULL) {
     483              Py_DECREF(func);
     484              PyErr_WriteUnraisable(context ? context : Py_None);
     485              return E_FAIL;
     486          }
     487          PyObject *py_riid = PyLong_FromVoidPtr((void *)riid);
     488          if (py_riid == NULL) {
     489              Py_DECREF(func);
     490              Py_DECREF(py_rclsid);
     491              PyErr_WriteUnraisable(context ? context : Py_None);
     492              return E_FAIL;
     493          }
     494          PyObject *py_ppv = PyLong_FromVoidPtr(ppv);
     495          if (py_ppv == NULL) {
     496              Py_DECREF(py_rclsid);
     497              Py_DECREF(py_riid);
     498              Py_DECREF(func);
     499              PyErr_WriteUnraisable(context ? context : Py_None);
     500              return E_FAIL;
     501          }
     502          result = PyObject_CallFunctionObjArgs(func,
     503                                                py_rclsid,
     504                                                py_riid,
     505                                                py_ppv,
     506                                                NULL);
     507          Py_DECREF(py_rclsid);
     508          Py_DECREF(py_riid);
     509          Py_DECREF(py_ppv);
     510      }
     511      Py_DECREF(func);
     512      if (!result) {
     513          PyErr_WriteUnraisable(context ? context : Py_None);
     514          return E_FAIL;
     515      }
     516  
     517      retval = PyLong_AsLong(result);
     518      if (PyErr_Occurred()) {
     519          PyErr_WriteUnraisable(context ? context : Py_None);
     520          retval = E_FAIL;
     521      }
     522      Py_DECREF(result);
     523      return retval;
     524  }
     525  
     526  STDAPI DllGetClassObject(REFCLSID rclsid,
     527                           REFIID riid,
     528                           LPVOID *ppv)
     529  {
     530      long result;
     531      PyGILState_STATE state;
     532  
     533      LoadPython();
     534      state = PyGILState_Ensure();
     535      result = Call_GetClassObject(rclsid, riid, ppv);
     536      PyGILState_Release(state);
     537      return result;
     538  }
     539  
     540  long Call_CanUnloadNow(void)
     541  {
     542      PyObject *mod, *func, *result;
     543      long retval;
     544      static PyObject *context;
     545  
     546      if (context == NULL)
     547          context = PyUnicode_InternFromString("_ctypes.DllCanUnloadNow");
     548  
     549      mod = PyImport_ImportModule("ctypes");
     550      if (!mod) {
     551  /*              OutputDebugString("Could not import ctypes"); */
     552          /* We assume that this error can only occur when shutting
     553             down, so we silently ignore it */
     554          PyErr_Clear();
     555          return E_FAIL;
     556      }
     557      /* Other errors cannot be raised, but are printed to stderr */
     558      func = PyObject_GetAttrString(mod, "DllCanUnloadNow");
     559      Py_DECREF(mod);
     560      if (!func) {
     561          PyErr_WriteUnraisable(context ? context : Py_None);
     562          return E_FAIL;
     563      }
     564  
     565      result = _PyObject_CallNoArgs(func);
     566      Py_DECREF(func);
     567      if (!result) {
     568          PyErr_WriteUnraisable(context ? context : Py_None);
     569          return E_FAIL;
     570      }
     571  
     572      retval = PyLong_AsLong(result);
     573      if (PyErr_Occurred()) {
     574          PyErr_WriteUnraisable(context ? context : Py_None);
     575          retval = E_FAIL;
     576      }
     577      Py_DECREF(result);
     578      return retval;
     579  }
     580  
     581  /*
     582    DllRegisterServer and DllUnregisterServer still missing
     583  */
     584  
     585  STDAPI DllCanUnloadNow(void)
     586  {
     587      long result;
     588      PyGILState_STATE state = PyGILState_Ensure();
     589      result = Call_CanUnloadNow();
     590      PyGILState_Release(state);
     591      return result;
     592  }
     593  
     594  #ifndef Py_NO_ENABLE_SHARED
     595  BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvRes)
     596  {
     597      switch(fdwReason) {
     598      case DLL_PROCESS_ATTACH:
     599          DisableThreadLibraryCalls(hinstDLL);
     600          break;
     601      }
     602      return TRUE;
     603  }
     604  #endif
     605  
     606  #endif
     607  
     608  /*
     609   Local Variables:
     610   compile-command: "cd .. && python setup.py -q build_ext"
     611   End:
     612  */