Home | History | Annotate | Download | only in _ctypes
      1 /*****************************************************************
      2   This file contains remnant Python 2.3 compatibility code that is no longer
      3   strictly required.
      4  *****************************************************************/
      5 
      6 #include "Python.h"
      7 #include "compile.h" /* required only for 2.3, as it seems */
      8 #include "frameobject.h"
      9 
     10 #include <ffi.h>
     11 #ifdef MS_WIN32
     12 #include <windows.h>
     13 #endif
     14 #include "ctypes.h"
     15 
     16 /**************************************************************/
     17 
     18 static void
     19 CThunkObject_dealloc(PyObject *_self)
     20 {
     21     CThunkObject *self = (CThunkObject *)_self;
     22     PyObject_GC_UnTrack(self);
     23     Py_XDECREF(self->converters);
     24     Py_XDECREF(self->callable);
     25     Py_XDECREF(self->restype);
     26     if (self->pcl_write)
     27         ffi_closure_free(self->pcl_write);
     28     PyObject_GC_Del(self);
     29 }
     30 
     31 static int
     32 CThunkObject_traverse(PyObject *_self, visitproc visit, void *arg)
     33 {
     34     CThunkObject *self = (CThunkObject *)_self;
     35     Py_VISIT(self->converters);
     36     Py_VISIT(self->callable);
     37     Py_VISIT(self->restype);
     38     return 0;
     39 }
     40 
     41 static int
     42 CThunkObject_clear(PyObject *_self)
     43 {
     44     CThunkObject *self = (CThunkObject *)_self;
     45     Py_CLEAR(self->converters);
     46     Py_CLEAR(self->callable);
     47     Py_CLEAR(self->restype);
     48     return 0;
     49 }
     50 
     51 PyTypeObject PyCThunk_Type = {
     52     PyVarObject_HEAD_INIT(NULL, 0)
     53     "_ctypes.CThunkObject",
     54     sizeof(CThunkObject),                       /* tp_basicsize */
     55     sizeof(ffi_type),                           /* tp_itemsize */
     56     CThunkObject_dealloc,                       /* tp_dealloc */
     57     0,                                          /* tp_print */
     58     0,                                          /* tp_getattr */
     59     0,                                          /* tp_setattr */
     60     0,                                          /* tp_compare */
     61     0,                                          /* tp_repr */
     62     0,                                          /* tp_as_number */
     63     0,                                          /* tp_as_sequence */
     64     0,                                          /* tp_as_mapping */
     65     0,                                          /* tp_hash */
     66     0,                                          /* tp_call */
     67     0,                                          /* tp_str */
     68     0,                                          /* tp_getattro */
     69     0,                                          /* tp_setattro */
     70     0,                                          /* tp_as_buffer */
     71     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,                            /* tp_flags */
     72     "CThunkObject",                             /* tp_doc */
     73     CThunkObject_traverse,                      /* tp_traverse */
     74     CThunkObject_clear,                         /* tp_clear */
     75     0,                                          /* tp_richcompare */
     76     0,                                          /* tp_weaklistoffset */
     77     0,                                          /* tp_iter */
     78     0,                                          /* tp_iternext */
     79     0,                                          /* tp_methods */
     80     0,                                          /* tp_members */
     81 };
     82 
     83 /**************************************************************/
     84 
     85 static void
     86 PrintError(char *msg, ...)
     87 {
     88     char buf[512];
     89     PyObject *f = PySys_GetObject("stderr");
     90     va_list marker;
     91 
     92     va_start(marker, msg);
     93     vsnprintf(buf, sizeof(buf), msg, marker);
     94     va_end(marker);
     95     if (f)
     96         PyFile_WriteString(buf, f);
     97     PyErr_Print();
     98 }
     99 
    100 #if (PY_VERSION_HEX < 0x02070000)
    101 PyCodeObject *
    102 PyCode_NewEmpty(const char *filename, const char *funcname, int firstlineno)
    103 {
    104     static PyObject *emptystring = NULL;
    105     static PyObject *nulltuple = NULL;
    106     PyObject *filename_ob = NULL;
    107     PyObject *funcname_ob = NULL;
    108     PyCodeObject *result = NULL;
    109     if (emptystring == NULL) {
    110         emptystring = PyString_FromString("");
    111         if (emptystring == NULL)
    112             goto failed;
    113     }
    114     if (nulltuple == NULL) {
    115         nulltuple = PyTuple_New(0);
    116         if (nulltuple == NULL)
    117             goto failed;
    118     }
    119     funcname_ob = PyString_FromString(funcname);
    120     if (funcname_ob == NULL)
    121         goto failed;
    122     filename_ob = PyString_FromString(filename);
    123     if (filename_ob == NULL)
    124         goto failed;
    125 
    126     result = PyCode_New(0,                      /* argcount */
    127                 0,                              /* nlocals */
    128                 0,                              /* stacksize */
    129                 0,                              /* flags */
    130                 emptystring,                    /* code */
    131                 nulltuple,                      /* consts */
    132                 nulltuple,                      /* names */
    133                 nulltuple,                      /* varnames */
    134                 nulltuple,                      /* freevars */
    135                 nulltuple,                      /* cellvars */
    136                 filename_ob,                    /* filename */
    137                 funcname_ob,                    /* name */
    138                 firstlineno,                    /* firstlineno */
    139                 emptystring                     /* lnotab */
    140                 );
    141 
    142 failed:
    143     Py_XDECREF(funcname_ob);
    144     Py_XDECREF(filename_ob);
    145     return result;
    146 }
    147 #endif
    148 
    149 
    150 /* after code that pyrex generates */
    151 void _ctypes_add_traceback(char *funcname, char *filename, int lineno)
    152 {
    153     PyObject *py_globals = 0;
    154     PyCodeObject *py_code = 0;
    155     PyFrameObject *py_frame = 0;
    156 
    157     py_globals = PyDict_New();
    158     if (!py_globals) goto bad;
    159     py_code = PyCode_NewEmpty(filename, funcname, lineno);
    160     if (!py_code) goto bad;
    161     py_frame = PyFrame_New(
    162         PyThreadState_Get(), /*PyThreadState *tstate,*/
    163         py_code,             /*PyCodeObject *code,*/
    164         py_globals,          /*PyObject *globals,*/
    165         0                    /*PyObject *locals*/
    166         );
    167     if (!py_frame) goto bad;
    168     py_frame->f_lineno = lineno;
    169     PyTraceBack_Here(py_frame);
    170   bad:
    171     Py_XDECREF(py_globals);
    172     Py_XDECREF(py_code);
    173     Py_XDECREF(py_frame);
    174 }
    175 
    176 #ifdef MS_WIN32
    177 /*
    178  * We must call AddRef() on non-NULL COM pointers we receive as arguments
    179  * to callback functions - these functions are COM method implementations.
    180  * The Python instances we create have a __del__ method which calls Release().
    181  *
    182  * The presence of a class attribute named '_needs_com_addref_' triggers this
    183  * behaviour.  It would also be possible to call the AddRef() Python method,
    184  * after checking for PyObject_IsTrue(), but this would probably be somewhat
    185  * slower.
    186  */
    187 static void
    188 TryAddRef(StgDictObject *dict, CDataObject *obj)
    189 {
    190     IUnknown *punk;
    191 
    192     if (NULL == PyDict_GetItemString((PyObject *)dict, "_needs_com_addref_"))
    193         return;
    194 
    195     punk = *(IUnknown **)obj->b_ptr;
    196     if (punk)
    197         punk->lpVtbl->AddRef(punk);
    198     return;
    199 }
    200 #endif
    201 
    202 /******************************************************************************
    203  *
    204  * Call the python object with all arguments
    205  *
    206  */
    207 static void _CallPythonObject(void *mem,
    208                               ffi_type *restype,
    209                               SETFUNC setfunc,
    210                               PyObject *callable,
    211                               PyObject *converters,
    212                               int flags,
    213                               void **pArgs)
    214 {
    215     Py_ssize_t i;
    216     PyObject *result;
    217     PyObject *arglist = NULL;
    218     Py_ssize_t nArgs;
    219     PyObject *error_object = NULL;
    220     int *space;
    221 #ifdef WITH_THREAD
    222     PyGILState_STATE state = PyGILState_Ensure();
    223 #endif
    224 
    225     nArgs = PySequence_Length(converters);
    226     /* Hm. What to return in case of error?
    227        For COM, 0xFFFFFFFF seems better than 0.
    228     */
    229     if (nArgs < 0) {
    230         PrintError("BUG: PySequence_Length");
    231         goto Done;
    232     }
    233 
    234     arglist = PyTuple_New(nArgs);
    235     if (!arglist) {
    236         PrintError("PyTuple_New()");
    237         goto Done;
    238     }
    239     for (i = 0; i < nArgs; ++i) {
    240         /* Note: new reference! */
    241         PyObject *cnv = PySequence_GetItem(converters, i);
    242         StgDictObject *dict;
    243         if (cnv)
    244             dict = PyType_stgdict(cnv);
    245         else {
    246             PrintError("Getting argument converter %d\n", i);
    247             goto Done;
    248         }
    249 
    250         if (dict && dict->getfunc && !_ctypes_simple_instance(cnv)) {
    251             PyObject *v = dict->getfunc(*pArgs, dict->size);
    252             if (!v) {
    253                 PrintError("create argument %d:\n", i);
    254                 Py_DECREF(cnv);
    255                 goto Done;
    256             }
    257             PyTuple_SET_ITEM(arglist, i, v);
    258             /* XXX XXX XX
    259                We have the problem that c_byte or c_short have dict->size of
    260                1 resp. 4, but these parameters are pushed as sizeof(int) bytes.
    261                BTW, the same problem occurs when they are pushed as parameters
    262             */
    263         } else if (dict) {
    264             /* Hm, shouldn't we use PyCData_AtAddress() or something like that instead? */
    265             CDataObject *obj = (CDataObject *)PyObject_CallFunctionObjArgs(cnv, NULL);
    266             if (!obj) {
    267                 PrintError("create argument %d:\n", i);
    268                 Py_DECREF(cnv);
    269                 goto Done;
    270             }
    271             if (!CDataObject_Check(obj)) {
    272                 Py_DECREF(obj);
    273                 Py_DECREF(cnv);
    274                 PrintError("unexpected result of create argument %d:\n", i);
    275                 goto Done;
    276             }
    277             memcpy(obj->b_ptr, *pArgs, dict->size);
    278             PyTuple_SET_ITEM(arglist, i, (PyObject *)obj);
    279 #ifdef MS_WIN32
    280             TryAddRef(dict, obj);
    281 #endif
    282         } else {
    283             PyErr_SetString(PyExc_TypeError,
    284                             "cannot build parameter");
    285             PrintError("Parsing argument %d\n", i);
    286             Py_DECREF(cnv);
    287             goto Done;
    288         }
    289         Py_DECREF(cnv);
    290         /* XXX error handling! */
    291         pArgs++;
    292     }
    293 
    294 #define CHECK(what, x) \
    295 if (x == NULL) _ctypes_add_traceback(what, "_ctypes/callbacks.c", __LINE__ - 1), PyErr_Print()
    296 
    297     if (flags & (FUNCFLAG_USE_ERRNO | FUNCFLAG_USE_LASTERROR)) {
    298         error_object = _ctypes_get_errobj(&space);
    299         if (error_object == NULL)
    300             goto Done;
    301         if (flags & FUNCFLAG_USE_ERRNO) {
    302             int temp = space[0];
    303             space[0] = errno;
    304             errno = temp;
    305         }
    306 #ifdef MS_WIN32
    307         if (flags & FUNCFLAG_USE_LASTERROR) {
    308             int temp = space[1];
    309             space[1] = GetLastError();
    310             SetLastError(temp);
    311         }
    312 #endif
    313     }
    314 
    315     result = PyObject_CallObject(callable, arglist);
    316     CHECK("'calling callback function'", result);
    317 
    318 #ifdef MS_WIN32
    319     if (flags & FUNCFLAG_USE_LASTERROR) {
    320         int temp = space[1];
    321         space[1] = GetLastError();
    322         SetLastError(temp);
    323     }
    324 #endif
    325     if (flags & FUNCFLAG_USE_ERRNO) {
    326         int temp = space[0];
    327         space[0] = errno;
    328         errno = temp;
    329     }
    330     Py_XDECREF(error_object);
    331 
    332     if ((restype != &ffi_type_void) && result) {
    333         PyObject *keep;
    334         assert(setfunc);
    335 #ifdef WORDS_BIGENDIAN
    336         /* See the corresponding code in callproc.c, around line 961 */
    337         if (restype->type != FFI_TYPE_FLOAT && restype->size < sizeof(ffi_arg))
    338             mem = (char *)mem + sizeof(ffi_arg) - restype->size;
    339 #endif
    340         keep = setfunc(mem, result, 0);
    341         CHECK("'converting callback result'", keep);
    342         /* keep is an object we have to keep alive so that the result
    343            stays valid.  If there is no such object, the setfunc will
    344            have returned Py_None.
    345 
    346            If there is such an object, we have no choice than to keep
    347            it alive forever - but a refcount and/or memory leak will
    348            be the result.  EXCEPT when restype is py_object - Python
    349            itself knows how to manage the refcount of these objects.
    350         */
    351         if (keep == NULL) /* Could not convert callback result. */
    352             PyErr_WriteUnraisable(callable);
    353         else if (keep == Py_None) /* Nothing to keep */
    354             Py_DECREF(keep);
    355         else if (setfunc != _ctypes_get_fielddesc("O")->setfunc) {
    356             if (-1 == PyErr_Warn(PyExc_RuntimeWarning,
    357                                  "memory leak in callback function."))
    358                 PyErr_WriteUnraisable(callable);
    359         }
    360     }
    361     Py_XDECREF(result);
    362   Done:
    363     Py_XDECREF(arglist);
    364 #ifdef WITH_THREAD
    365     PyGILState_Release(state);
    366 #endif
    367 }
    368 
    369 static void closure_fcn(ffi_cif *cif,
    370                         void *resp,
    371                         void **args,
    372                         void *userdata)
    373 {
    374     CThunkObject *p = (CThunkObject *)userdata;
    375 
    376     _CallPythonObject(resp,
    377                       p->ffi_restype,
    378                       p->setfunc,
    379                       p->callable,
    380                       p->converters,
    381                       p->flags,
    382                       args);
    383 }
    384 
    385 static CThunkObject* CThunkObject_new(Py_ssize_t nArgs)
    386 {
    387     CThunkObject *p;
    388     Py_ssize_t i;
    389 
    390     p = PyObject_GC_NewVar(CThunkObject, &PyCThunk_Type, nArgs);
    391     if (p == NULL) {
    392         PyErr_NoMemory();
    393         return NULL;
    394     }
    395 
    396     p->pcl_write = NULL;
    397     p->pcl_exec = NULL;
    398     memset(&p->cif, 0, sizeof(p->cif));
    399     p->flags = 0;
    400     p->converters = NULL;
    401     p->callable = NULL;
    402     p->restype = NULL;
    403     p->setfunc = NULL;
    404     p->ffi_restype = NULL;
    405 
    406     for (i = 0; i < nArgs + 1; ++i)
    407         p->atypes[i] = NULL;
    408     PyObject_GC_Track((PyObject *)p);
    409     return p;
    410 }
    411 
    412 CThunkObject *_ctypes_alloc_callback(PyObject *callable,
    413                                     PyObject *converters,
    414                                     PyObject *restype,
    415                                     int flags)
    416 {
    417     int result;
    418     CThunkObject *p;
    419     Py_ssize_t nArgs, i;
    420     ffi_abi cc;
    421 
    422     nArgs = PySequence_Size(converters);
    423     p = CThunkObject_new(nArgs);
    424     if (p == NULL)
    425         return NULL;
    426 
    427     assert(CThunk_CheckExact(p));
    428 
    429     p->pcl_write = ffi_closure_alloc(sizeof(ffi_closure),
    430 				     &p->pcl_exec);
    431     if (p->pcl_write == NULL) {
    432         PyErr_NoMemory();
    433         goto error;
    434     }
    435 
    436     p->flags = flags;
    437     for (i = 0; i < nArgs; ++i) {
    438         PyObject *cnv = PySequence_GetItem(converters, i);
    439         if (cnv == NULL)
    440             goto error;
    441         p->atypes[i] = _ctypes_get_ffi_type(cnv);
    442         Py_DECREF(cnv);
    443     }
    444     p->atypes[i] = NULL;
    445 
    446     Py_INCREF(restype);
    447     p->restype = restype;
    448     if (restype == Py_None) {
    449         p->setfunc = NULL;
    450         p->ffi_restype = &ffi_type_void;
    451     } else {
    452         StgDictObject *dict = PyType_stgdict(restype);
    453         if (dict == NULL || dict->setfunc == NULL) {
    454           PyErr_SetString(PyExc_TypeError,
    455                           "invalid result type for callback function");
    456           goto error;
    457         }
    458         p->setfunc = dict->setfunc;
    459         p->ffi_restype = &dict->ffi_type_pointer;
    460     }
    461 
    462     cc = FFI_DEFAULT_ABI;
    463 #if defined(MS_WIN32) && !defined(_WIN32_WCE) && !defined(MS_WIN64)
    464     if ((flags & FUNCFLAG_CDECL) == 0)
    465         cc = FFI_STDCALL;
    466 #endif
    467     result = ffi_prep_cif(&p->cif, cc,
    468                           Py_SAFE_DOWNCAST(nArgs, Py_ssize_t, int),
    469                           _ctypes_get_ffi_type(restype),
    470                           &p->atypes[0]);
    471     if (result != FFI_OK) {
    472         PyErr_Format(PyExc_RuntimeError,
    473                      "ffi_prep_cif failed with %d", result);
    474         goto error;
    475     }
    476 #if defined(X86_DARWIN) || defined(POWERPC_DARWIN)
    477     result = ffi_prep_closure(p->pcl_write, &p->cif, closure_fcn, p);
    478 #else
    479     result = ffi_prep_closure_loc(p->pcl_write, &p->cif, closure_fcn,
    480 				  p,
    481 				  p->pcl_exec);
    482 #endif
    483     if (result != FFI_OK) {
    484         PyErr_Format(PyExc_RuntimeError,
    485                      "ffi_prep_closure failed with %d", result);
    486         goto error;
    487     }
    488 
    489     Py_INCREF(converters);
    490     p->converters = converters;
    491     Py_INCREF(callable);
    492     p->callable = callable;
    493     return p;
    494 
    495   error:
    496     Py_XDECREF(p);
    497     return NULL;
    498 }
    499 
    500 #ifdef MS_WIN32
    501 
    502 static void LoadPython(void)
    503 {
    504     if (!Py_IsInitialized()) {
    505 #ifdef WITH_THREAD
    506         PyEval_InitThreads();
    507 #endif
    508         Py_Initialize();
    509     }
    510 }
    511 
    512 /******************************************************************/
    513 
    514 long Call_GetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv)
    515 {
    516     PyObject *mod, *func, *result;
    517     long retval;
    518     static PyObject *context;
    519 
    520     if (context == NULL)
    521         context = PyString_InternFromString("_ctypes.DllGetClassObject");
    522 
    523     mod = PyImport_ImportModuleNoBlock("ctypes");
    524     if (!mod) {
    525         PyErr_WriteUnraisable(context ? context : Py_None);
    526         /* There has been a warning before about this already */
    527         return E_FAIL;
    528     }
    529 
    530     func = PyObject_GetAttrString(mod, "DllGetClassObject");
    531     Py_DECREF(mod);
    532     if (!func) {
    533         PyErr_WriteUnraisable(context ? context : Py_None);
    534         return E_FAIL;
    535     }
    536 
    537     {
    538         PyObject *py_rclsid = PyLong_FromVoidPtr((void *)rclsid);
    539         PyObject *py_riid = PyLong_FromVoidPtr((void *)riid);
    540         PyObject *py_ppv = PyLong_FromVoidPtr(ppv);
    541         if (!py_rclsid || !py_riid || !py_ppv) {
    542             Py_XDECREF(py_rclsid);
    543             Py_XDECREF(py_riid);
    544             Py_XDECREF(py_ppv);
    545             Py_DECREF(func);
    546             PyErr_WriteUnraisable(context ? context : Py_None);
    547             return E_FAIL;
    548         }
    549         result = PyObject_CallFunctionObjArgs(func,
    550                                               py_rclsid,
    551                                               py_riid,
    552                                               py_ppv,
    553                                               NULL);
    554         Py_DECREF(py_rclsid);
    555         Py_DECREF(py_riid);
    556         Py_DECREF(py_ppv);
    557     }
    558     Py_DECREF(func);
    559     if (!result) {
    560         PyErr_WriteUnraisable(context ? context : Py_None);
    561         return E_FAIL;
    562     }
    563 
    564     retval = PyInt_AsLong(result);
    565     if (PyErr_Occurred()) {
    566         PyErr_WriteUnraisable(context ? context : Py_None);
    567         retval = E_FAIL;
    568     }
    569     Py_DECREF(result);
    570     return retval;
    571 }
    572 
    573 STDAPI DllGetClassObject(REFCLSID rclsid,
    574                          REFIID riid,
    575                          LPVOID *ppv)
    576 {
    577     long result;
    578 #ifdef WITH_THREAD
    579     PyGILState_STATE state;
    580 #endif
    581 
    582     LoadPython();
    583 #ifdef WITH_THREAD
    584     state = PyGILState_Ensure();
    585 #endif
    586     result = Call_GetClassObject(rclsid, riid, ppv);
    587 #ifdef WITH_THREAD
    588     PyGILState_Release(state);
    589 #endif
    590     return result;
    591 }
    592 
    593 long Call_CanUnloadNow(void)
    594 {
    595     PyObject *mod, *func, *result;
    596     long retval;
    597     static PyObject *context;
    598 
    599     if (context == NULL)
    600         context = PyString_InternFromString("_ctypes.DllCanUnloadNow");
    601 
    602     mod = PyImport_ImportModuleNoBlock("ctypes");
    603     if (!mod) {
    604 /*              OutputDebugString("Could not import ctypes"); */
    605         /* We assume that this error can only occur when shutting
    606            down, so we silently ignore it */
    607         PyErr_Clear();
    608         return E_FAIL;
    609     }
    610     /* Other errors cannot be raised, but are printed to stderr */
    611     func = PyObject_GetAttrString(mod, "DllCanUnloadNow");
    612     Py_DECREF(mod);
    613     if (!func) {
    614         PyErr_WriteUnraisable(context ? context : Py_None);
    615         return E_FAIL;
    616     }
    617 
    618     result = PyObject_CallFunction(func, NULL);
    619     Py_DECREF(func);
    620     if (!result) {
    621         PyErr_WriteUnraisable(context ? context : Py_None);
    622         return E_FAIL;
    623     }
    624 
    625     retval = PyInt_AsLong(result);
    626     if (PyErr_Occurred()) {
    627         PyErr_WriteUnraisable(context ? context : Py_None);
    628         retval = E_FAIL;
    629     }
    630     Py_DECREF(result);
    631     return retval;
    632 }
    633 
    634 /*
    635   DllRegisterServer and DllUnregisterServer still missing
    636 */
    637 
    638 STDAPI DllCanUnloadNow(void)
    639 {
    640     long result;
    641 #ifdef WITH_THREAD
    642     PyGILState_STATE state = PyGILState_Ensure();
    643 #endif
    644     result = Call_CanUnloadNow();
    645 #ifdef WITH_THREAD
    646     PyGILState_Release(state);
    647 #endif
    648     return result;
    649 }
    650 
    651 #ifndef Py_NO_ENABLE_SHARED
    652 BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvRes)
    653 {
    654     switch(fdwReason) {
    655     case DLL_PROCESS_ATTACH:
    656         DisableThreadLibraryCalls(hinstDLL);
    657         break;
    658     }
    659     return TRUE;
    660 }
    661 #endif
    662 
    663 #endif
    664 
    665 /*
    666  Local Variables:
    667  compile-command: "cd .. && python setup.py -q build_ext"
    668  End:
    669 */
    670