VirtualBox

Changeset 86333 in vbox for trunk/src/libs/xpcom18a4/python


Ignore:
Timestamp:
Sep 28, 2020 8:01:18 PM (4 years ago)
Author:
vboxsync
Message:

xpcom/python: Initial Py_LIMITED_API support. bugref:9840

Location:
trunk/src/libs/xpcom18a4/python
Files:
10 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/libs/xpcom18a4/python/Makefile.kmk

    r86245 r86333  
    279279endif
    280280
     281 ifndef VBOX_WITH_ONLY_PYTHON_LIMITED_API
     282
    281283ifdef VBOX_PYTHON33_INC
    282284#
     
    582584 endif
    583585endif
     586
     587 endif # !VBOX_WITH_ONLY_PYTHON_LIMITED_API
     588
     589 ifndef VBOX_WITHOUT_PYTHON_LIMITED_API
     590#
     591# If there is python 3.3 or later present, we can build a generic
     592# 3.x extension.  Since 3.3 and 3.4 are rather old, we will pick
     593# those headers last.
     594#
     595# Note! No library dependencies are needed here (at least that's
     596#       how the xxlimited.so demo extension is done on linux and darwin).
     597# Note! The 'm' ABI suffix was discontinued in 3.8.
     598# TODO: ASSUMING that we don't need a different headers for pymalloc
     599#       ('m' builds < 3.8) and CRT malloc.
     600#
     601VBOX_PYTHON_LIMITED_API_VER := $(firstword $(foreach ver, 35 36 38 39 310   34 33 \
     602,$(if-expr defined(VBOX_PYTHON$(ver)_INC),$(ver),)$(if-expr defined(VBOX_PYTHON$(ver)m_INC),$(ver)m,)))
     603  ifneq ($(VBOX_PYTHON_LIMITED_API_VER),)
     604DLLS += VBoxPython3
     605VBoxPython3_EXTENDS      = VBoxPythonBase
     606VBoxPython3_DEFS         = $(filter-out VBOX_PYXPCOM_VERSIONED,$(VBoxPythonBase_DEFS)) Py_LIMITED_API=0x03030000
     607VBoxPython3_INCS         = $(VBoxPythonBase_INCS) $(VBOX_PYTHON$(VBOX_PYTHON_LIMITED_API_VER)_INC)
     608
     609DLLS += VBoxPython3m
     610VBoxPython3m_EXTENDS     = VBoxPythonBase_m
     611VBoxPython3m_DEFS        = $(filter-out VBOX_PYXPCOM_VERSIONED,$(VBoxPythonBase_m_DEFS)) Py_LIMITED_API=0x03030000
     612VBoxPython3m_INCS        = $(VBoxPythonBase_m_INCS) $(VBOX_PYTHON$(VBOX_PYTHON_LIMITED_API_VER)_INC)
     613  endif
     614 endif # VBOX_WITH_PYTHON_LIMITED_API
    584615
    585616endif # VBOX_ONLY_SDK
  • trunk/src/libs/xpcom18a4/python/src/PyGBase.cpp

    r65842 r86333  
    154154
    155155#ifdef DEBUG_FULL
    156         LogF("PyGatewayBase: created %s", m_pPyObject ? m_pPyObject->ob_type->tp_name : "<NULL>");
     156        LogF("PyGatewayBase: created %s", m_pPyObject ? PyXPCOM_ObTypeName(m_pPyObject) : "<NULL>");
    157157#endif
    158158}
     
    400400                                // reporting the fact that QI failed - this error
    401401                                // may provide clues!
    402                                 PyXPCOM_LogError("The _QueryInterface_ method returned an object of type '%s', but an interface was expected\n", result->ob_type->tp_name);
     402                                PyXPCOM_LogError("The _QueryInterface_ method returned an object of type '%s', but an interface was expected\n", PyXPCOM_ObTypeName(result));
    403403                                // supports remains false
    404404                        }
     
    512512                        // The exception handler succeeded, but returned other than
    513513                        // int or None.
    514                         PyXPCOM_LogError("The _CallMethodException_ handler returned object of type '%s' - None or an integer expected\n", err_result->ob_type->tp_name);
     514                        PyXPCOM_LogError("The _CallMethodException_ handler returned object of type '%s' - None or an integer expected\n", PyXPCOM_ObTypeName(err_result));
    515515                }
    516516                Py_XDECREF(err_result);
  • trunk/src/libs/xpcom18a4/python/src/PyGInputStream.cpp

    r11746 r86333  
    104104        nsresult nr = InvokeNativeViaPolicy(methodName, &ret, "i", count);
    105105        if (NS_SUCCEEDED(nr)) {
    106 #ifndef VBOX /* unsafe cast on 64-bit hosts. */
     106#if 0 /* VBox: new buffer protocol (though I could use it for Py_LIMITED_API and ditch the warning, but cpython specific) */
     107                Py_buffer py_view;
     108                if (PyObject_GetBuffer(ret, &py_view, PyBUF_SIMPLE) == 0) {
     109                        if (py_view.len <= count) {
     110                                count = py_view.len;
     111                        } else {
     112                                PyXPCOM_LogWarning("nsIInputStream::read() was asked for %d bytes, but the string returned is %d bytes - truncating!\n", count, py_size);
     113                        }
     114                        memcpy(buf, py_view.py_buf, count);
     115                        PyBuffer_Release(&py_view);
     116                        *_retval = count;
     117                } else {
     118                        PyErr_Format(PyExc_TypeError, "nsIInputStream::read() method must return a buffer object - not a '%s' object", PyXPCOM_ObTypeName(ret));
     119                        nr = HandleNativeGatewayError(methodName);
     120                }
     121#else  /* Old protocol: */
     122# ifndef VBOX /* unsafe cast on 64-bit hosts. */
    107123                PRUint32 py_size;
    108124                const void *py_buf;
    109125                if (PyObject_AsReadBuffer(ret, &py_buf, (Py_ssize_t*)&py_size)!=0) {
    110 #else  /* VBOX */
     126# else  /* VBOX */
    111127                const void *py_buf;
    112 # if PY_VERSION_HEX >= 0x02050000 || defined(PY_SSIZE_T_MIN)
     128#  if PY_VERSION_HEX >= 0x02050000 || defined(PY_SSIZE_T_MIN)
    113129                Py_ssize_t py_size;
    114 # else
     130#  else
    115131                int py_size;
     132#  endif
     133                if (PyObject_AsReadBuffer(ret, &py_buf, &py_size)!=0) {
    116134# endif /* VBOX */
    117                 if (PyObject_AsReadBuffer(ret, &py_buf, &py_size)!=0) {
    118 #endif /* VBOX */
    119                         PyErr_Format(PyExc_TypeError, "nsIInputStream::read() method must return a buffer object - not a '%s' object", ret->ob_type->tp_name);
     135                        PyErr_Format(PyExc_TypeError, "nsIInputStream::read() method must return a buffer object - not a '%s' object", PyXPCOM_ObTypeName(ret));
    120136                        nr = HandleNativeGatewayError(methodName);
    121137                } else {
     
    127143                        *_retval = py_size;
    128144                }
     145#endif
    129146        }
    130147        return nr;
  • trunk/src/libs/xpcom18a4/python/src/PyGStub.cpp

    r21178 r86333  
    160160                        // The exception handler succeeded, but returned other than
    161161                        // int or None.
    162                         PyXPCOM_LogError("The _CallMethodException_ handler returned object of type '%s' - None or an integer expected\n", err_result->ob_type->tp_name);
     162                        PyXPCOM_LogError("The _CallMethodException_ handler returned object of type '%s' - None or an integer expected\n", PyXPCOM_ObTypeName(err_result));
    163163                }
    164164                Py_XDECREF(err_result);
  • trunk/src/libs/xpcom18a4/python/src/PyIID.cpp

    r86312 r86333  
    6868#else
    6969                if (PyObject_CheckBuffer(obBuf)) {
     70# ifndef Py_LIMITED_API
    7071                        Py_buffer view;
    7172                        if (PyObject_GetBuffer(obBuf, &view, PyBUF_CONTIG_RO) != 0) {
     
    7576                        Py_ssize_t size = view.len;
    7677                        const void *buf = view.buf;
     78# else  /* Py_LIMITED_API - the buffer API is non-existant, from what I can tell */
     79                        const void *buf = NULL;
     80                        Py_ssize_t size = 0;
     81                        if (PyObject_AsReadBuffer(obBuf, &buf, &size) != 0) {
     82                                PyErr_Format(PyExc_ValueError, "Could not get read-only buffer from object");
     83                                return NULL;
     84                        }
     85# endif /* Py_LIMITED_API */
    7786#endif
    7887                        if (size != sizeof(nsIID) || buf==NULL) {
    79 #if PY_MAJOR_VERSION >= 3
     88#if PY_MAJOR_VERSION >= 3 && !defined(Py_LIMITED_API)
    8089                                PyBuffer_Release(&view);
    8190#endif
     
    99108                                ptr += sizeof(PRUint8);
    100109                        }
    101 #if PY_MAJOR_VERSION >= 3
     110#if PY_MAJOR_VERSION >= 3 && !defined(Py_LIMITED_API)
    102111                        PyBuffer_Release(&view);
    103112#endif
     
    135144                        return PR_FALSE;
    136145                }
     146#ifndef Py_LIMITED_API
    137147        } else if (ob->ob_type == &type) {
     148#else
     149        } else if (ob->ob_type == Py_nsIID::GetTypeObject()) {
     150#endif
    138151                iid = ((Py_nsIID *)ob)->m_iid;
    139152        } else if (PyObject_HasAttrString(ob, "__class__")) {
     
    144157                        return PR_FALSE;
    145158                }
     159#ifndef Py_LIMITED_API
    146160                if (use_ob->ob_type != &type) {
     161#else
     162                if (use_ob->ob_type != Py_nsIID::GetTypeObject()) {
     163#endif
    147164                        Py_DECREF(use_ob);
    148165                        PyErr_SetString(PyExc_TypeError, "instance _iidobj_ attributes must be raw IID object");
     
    152169                Py_DECREF(use_ob);
    153170        } else {
    154                 PyErr_Format(PyExc_TypeError, "Objects of type '%s' can not be converted to an IID", ob->ob_type->tp_name);
     171                PyErr_Format(PyExc_TypeError, "Objects of type '%s' can not be converted to an IID", PyXPCOM_ObTypeName(ob));
    155172                ok = PR_FALSE;
    156173        }
     
    164181// objects.  However, in almost all cases, functions that expect a CLSID/IID
    165182// as a param will accept either a string object, or a native Py_nsIID object.
     183#ifndef Py_LIMITED_API
    166184PyTypeObject Py_nsIID::type =
    167185{
     
    202220        0,                                              /* tp_base */
    203221};
     222#else  /* Py_LIMITED_API */
     223NS_EXPORT_STATIC_MEMBER_(PyTypeObject *) Py_nsIID::s_pType = NULL;
     224
     225PyTypeObject *Py_nsIID::GetTypeObject(void)
     226{
     227        PyTypeObject *pTypeObj = Py_nsIID::s_pType;
     228        if (pTypeObj)
     229                return pTypeObj;
     230
     231        PyType_Slot aTypeSlots[] = {
     232                { Py_tp_base,           &PyType_Type },
     233                { Py_tp_dealloc,        (void *)(uintptr_t)&Py_nsIID::PyTypeMethod_dealloc },
     234                { Py_tp_getattr,        (void *)(uintptr_t)&Py_nsIID::PyTypeMethod_getattr },
     235                { Py_tp_repr,           (void *)(uintptr_t)&Py_nsIID::PyTypeMethod_repr },
     236                { Py_tp_hash,           (void *)(uintptr_t)&Py_nsIID::PyTypeMethod_hash },
     237                { Py_tp_str,            (void *)(uintptr_t)&Py_nsIID::PyTypeMethod_str },
     238                { Py_tp_richcompare,    (void *)(uintptr_t)&Py_nsIID::PyTypeMethod_richcompare },
     239                { 0, NULL } /* terminator */
     240        };
     241        PyType_Spec TypeSpec = {
     242                /* .name: */            "IID",
     243                /* .basicsize: */       sizeof(Py_nsIID),
     244                /* .itemsize: */        0,
     245                /* .flags: */           0,
     246                /* .slots: */           aTypeSlots,
     247        };
     248
     249        PyObject *exc_typ = NULL, *exc_val = NULL, *exc_tb = NULL;
     250        PyErr_Fetch(&exc_typ, &exc_val, &exc_tb); /* goes south in PyType_Ready if we don't clear exceptions first. */
     251
     252        pTypeObj = (PyTypeObject *)PyType_FromSpec(&TypeSpec);
     253        assert(pTypeObj);
     254
     255        PyErr_Restore(exc_typ, exc_val, exc_tb);
     256        Py_nsIID::s_pType = pTypeObj;
     257        return pTypeObj;
     258}
     259#endif /* Py_LIMITED_API */
    204260
    205261Py_nsIID::Py_nsIID(const nsIID &riid)
    206262{
     263#ifndef Py_LIMITED_API
    207264        ob_type = &type;
     265#else
     266        ob_type = GetTypeObject();
     267#endif
    208268        _Py_NewReference(this);
    209269        m_iid = riid;
  • trunk/src/libs/xpcom18a4/python/src/PyISupports.cpp

    r86310 r86333  
    129129}
    130130
     131#ifndef Py_LIMITED_API
    131132Py_nsISupports::Py_nsISupports(nsISupports *punk, const nsIID &iid, PyTypeObject *this_type)
    132 {
     133#else
     134Py_nsISupports::Py_nsISupports(nsISupports *punk, const nsIID &iid, PyXPCOM_TypeObject *this_type)
     135#endif
     136{
     137#ifndef Py_LIMITED_API
    133138        ob_type = this_type;
     139#else
     140        ob_type = this_type->m_pTypeObj;
     141        m_pMyTypeObj = this_type;
     142#endif
    134143        m_obj = punk;
    135144        m_iid = iid;
     
    217226                return ret;
    218227        }
     228#ifndef Py_LIMITED_API
    219229        PyXPCOM_TypeObject *this_type = (PyXPCOM_TypeObject *)ob_type;
     230#else
     231        PyXPCOM_TypeObject *this_type = m_pMyTypeObj;
     232#endif
    220233#if PY_MAJOR_VERSION <= 2
    221234        return Py_FindMethodInChain(&this_type->chain, this, (char *)name);
     
    223236        PyMethodChain *chain = &this_type->chain;
    224237        if (name[0] == '_' && name[1] == '_') {
     238# ifndef Py_LIMITED_API /** @todo ? */
    225239            if (!strcmp(name, "__doc__")) {
    226240                const char *doc = ob_type->tp_doc;
     
    228242                    return PyUnicode_FromString(doc);
    229243            }
     244# endif
    230245        }
    231246        while (chain) {
     
    247262        char buf[128];
    248263#ifdef VBOX
    249         snprintf(buf, sizeof(buf), "%s has read-only attributes", ob_type->tp_name );
    250 #else
    251         sprintf(buf, "%s has read-only attributes", ob_type->tp_name );
     264        snprintf(buf, sizeof(buf), "%s has read-only attributes", PyXPCOM_ObTypeName(this) );
     265#else
     266        sprintf(buf, "%s has read-only attributes", PyXPCOM_ObTypeName(this) );
    252267#endif
    253268        PyErr_SetString(PyExc_TypeError, buf);
     
    272287        if ( !Check(ob) )
    273288        {
    274                 PyErr_Format(PyExc_TypeError, "Objects of type '%s' can not be used as COM objects", ob->ob_type->tp_name);
     289                PyErr_Format(PyExc_TypeError, "Objects of type '%s' can not be used as COM objects", PyXPCOM_ObTypeName(ob));
    275290                goto done;
    276291        }
     
    390405// Interface conversions
    391406/*static*/void
     407#ifndef Py_LIMITED_API
    392408Py_nsISupports::RegisterInterface( const nsIID &iid, PyTypeObject *t)
     409#else
     410Py_nsISupports::RegisterInterface( const nsIID &iid, PyXPCOM_TypeObject *t)
     411#endif
    393412{
    394413        if (mapIIDToType==NULL)
     
    426445        }
    427446
     447#ifndef Py_LIMITED_API
    428448        PyTypeObject *createType = NULL;
     449#else
     450        PyXPCOM_TypeObject *createType = NULL;
     451#endif
    429452        // If the IID is for nsISupports, dont bother with
    430453        // a map lookup as we know the type!
     
    435458
    436459                if (mapIIDToType != NULL)
     460#ifndef Py_LIMITED_API
    437461                        createType = (PyTypeObject *)PyDict_GetItem(mapIIDToType, obiid);
     462#else
     463                        createType = (PyXPCOM_TypeObject *)PyDict_GetItem(mapIIDToType, obiid);
     464#endif
    438465                Py_DECREF(obiid);
    439466        }
    440467        if (createType==NULL)
    441468                createType = Py_nsISupports::type;
     469#ifndef Py_LIMITED_API
    442470        // Check it is indeed one of our types.
    443471        if (!PyXPCOM_TypeObject::IsType(createType)) {
     
    447475        // we can now safely cast the thing to a PyComTypeObject and use it
    448476        PyXPCOM_TypeObject *myCreateType = (PyXPCOM_TypeObject *)createType;
     477#else  /* Since the mapIIDToType is only updated by us, there should be no need for the above. */
     478        PyXPCOM_TypeObject * const myCreateType = createType;
     479#endif
    449480        if (myCreateType->ctor==NULL) {
    450481                PyErr_SetString(PyExc_TypeError, "The type does not declare a PyCom constructor");
  • trunk/src/libs/xpcom18a4/python/src/PyXPCOM.h

    r64330 r86333  
    166166class Py_nsISupports;
    167167
     168
     169/** @name VBox limited API hacks:
     170 * @{  */
     171#ifndef Py_LIMITED_API
     172
     173# define PyXPCOM_ObTypeName(obj) (Py_TYPE(obj)->tp_name)
     174
     175#else /* Py_LIMITED_API */
     176
     177const char *PyXPCOMGetObTypeName(PyTypeObject *pTypeObj);
     178# define PyXPCOM_ObTypeName(obj) PyXPCOMGetObTypeName(Py_TYPE(obj))
     179
     180/** @todo shouldn't be using PyUnicode_AsUTF8 from cpython/unicodeobject.h! */
     181# undef PyUnicode_AsUTF8
     182extern "C" PyAPI_FUNC(const char *) PyUnicode_AsUTF8(PyObject *);
     183
     184/** @todo shouldn't be using PyUnicode_AsUTF8AndSize from cpython/unicodeobject.h! */
     185# undef PyUnicode_AsUTF8AndSize
     186extern "C" PyAPI_FUNC(const char *) PyUnicode_AsUTF8AndSize(PyObject *, Py_ssize_t *);
     187
     188DECLINLINE(int) PyRun_SimpleString(const char *pszCode)
     189{
     190    /* Get the main mode dictionary: */
     191    PyObject *pMainMod = PyImport_AddModule("__main__");
     192    if (pMainMod) {
     193        PyObject *pMainModDict = PyModule_GetDict(pMainMod);
     194
     195        /* Compile and run the code. */
     196        PyObject *pCodeObject = Py_CompileString(pszCode, "PyXPCOM", Py_file_input);
     197        if (pCodeObject) {
     198            PyObject *pResult = PyEval_EvalCode(pCodeObject, pMainModDict, pMainModDict);
     199            Py_DECREF(pCodeObject);
     200            if (pResult) {
     201                Py_DECREF(pResult);
     202                return 0;
     203            }
     204            PyErr_Print();
     205        }
     206    }
     207    return -1;
     208}
     209
     210DECLINLINE(PyObject *) PyTuple_GET_ITEM(PyObject *pTuple, Py_ssize_t idx)
     211{
     212    return PyTuple_GetItem(pTuple, idx);
     213}
     214
     215DECLINLINE(int) PyTuple_SET_ITEM(PyObject *pTuple, Py_ssize_t idx, PyObject *pItem)
     216{
     217    int rc = PyTuple_SetItem(pTuple, idx, pItem); /* Steals pItem ref, just like PyTuple_SET_ITEM. */
     218    Assert(rc == 0);
     219    return rc;
     220}
     221
     222DECLINLINE(int) PyList_SET_ITEM(PyObject *pList, Py_ssize_t idx, PyObject *pItem)
     223{
     224    int rc = PyList_SetItem(pList, idx, pItem); /* Steals pItem ref, just like PyList_SET_ITEM. */
     225    Assert(rc == 0);
     226    return rc;
     227}
     228
     229DECLINLINE(Py_ssize_t) PyBytes_GET_SIZE(PyObject *pBytes)
     230{
     231    return PyBytes_Size(pBytes);
     232}
     233
     234DECLINLINE(const char *) PyBytes_AS_STRING(PyObject *pBytes)
     235{
     236    return PyBytes_AsString(pBytes);
     237}
     238
     239DECLINLINE(Py_ssize_t) PyUnicode_GET_SIZE(PyObject *pUnicode)
     240{
     241    /* Note! Currently only used for testing for zero or 1 codepoints, so we don't
     242       really need to deal with the different way these two treats surrogate pairs. */
     243# if Py_LIMITED_API >= 0x03030000
     244    return PyUnicode_GetLength(pUnicode);
     245# else
     246    return PyUnicode_GetSize(pUnicode);
     247# endif
     248}
     249
     250# define PyObject_CheckBuffer(pAllegedBuffer) PyObject_CheckReadBuffer(pAllegedBuffer)
     251
     252# include <iprt/asm.h>
     253DECLINLINE(Py_hash_t) _Py_HashPointer(void *p)
     254{
     255    Py_hash_t uHash = (Py_hash_t)RT_CONCAT(ASMRotateRightU,ARCH_BITS)((uintptr_t)p, 4);
     256    return uHash != -1 ? uHash : -2;
     257}
     258
     259#endif /* Py_LIMITED_API */
     260/** @} */
     261
     262
    168263/*************************************************************************
    169264**************************************************************************
     
    264359// Base class for (most of) the type objects.
    265360
     361#ifndef Py_LIMITED_API
    266362class PYXPCOM_EXPORT PyXPCOM_TypeObject : public PyTypeObject {
     363#else
     364class PYXPCOM_EXPORT PyXPCOM_TypeObject : public PyObject {
     365#endif
    267366public:
    268367        PyXPCOM_TypeObject(
     
    291390#else
    292391        static long Py_hash(PyObject *self);
     392#endif
     393#ifdef Py_LIMITED_API
     394        PyTypeObject *m_pTypeObj; /**< The python type object we wrap. */
    293395#endif
    294396};
     
    321423        nsCOMPtr<nsISupports> m_obj;
    322424        nsIID m_iid;
     425#ifdef Py_LIMITED_API
     426        /** Because PyXPCOM_TypeObject cannot inherit from PyTypeObject in
     427         * Py_LIMITED_API mode, we cannot use ob_type to get to the method list.
     428         * Instead of we store it here. */
     429        PyXPCOM_TypeObject *m_pMyTypeObj;
     430#endif
    323431
    324432        // Given an nsISupports and an Interface ID, create and return an object
     
    370478        static PyObject *mapIIDToType;
    371479        static void SafeRelease(Py_nsISupports *ob);
     480#ifndef Py_LIMITED_API
    372481        static void RegisterInterface( const nsIID &iid, PyTypeObject *t);
     482#else
     483        static void RegisterInterface( const nsIID &iid, PyXPCOM_TypeObject *t);
     484#endif
    373485        static void InitType();
    374486#ifdef VBOX_DEBUG_LIFETIMES
     
    393505        Py_nsISupports(nsISupports *p,
    394506                            const nsIID &iid,
     507#ifndef Py_LIMITED_API
    395508                            PyTypeObject *type);
     509#else
     510                            PyXPCOM_TypeObject *type);
     511#endif
    396512
    397513        // Make a default wrapper for an ISupports (which is an
     
    425541        IsEqual(PyObject *ob) {
    426542                return ob &&
     543#ifndef Py_LIMITED_API
    427544                       ob->ob_type== &type &&
     545#else
     546                       ob->ob_type == s_pType &&
     547#endif
    428548                       m_iid.Equals(((Py_nsIID *)ob)->m_iid);
    429549        }
     
    454574        static PyObject *PyTypeMethod_str(PyObject *self);
    455575        static void PyTypeMethod_dealloc(PyObject *self);
     576#ifndef Py_LIMITED_API
    456577        static NS_EXPORT_STATIC_MEMBER_(PyTypeObject) type;
     578#else
     579        static NS_EXPORT_STATIC_MEMBER_(PyTypeObject *) s_pType;
     580        static PyTypeObject *GetTypeObject(void);
     581#endif
    457582        static NS_EXPORT_STATIC_MEMBER_(PyMethodDef) methods[];
    458583};
     
    757882                // See "pending calls" comment below.  We reach into the Python
    758883                // implementation to see if we are the first call on the stack.
     884# ifndef Py_LIMITED_API
    759885                if (PyThreadState_Get()->gilstate_counter==1) {
     886# else
     887                if (state == PyGILState_UNLOCKED) {
     888# endif
    760889                        PyXPCOM_MakePendingCalls();
    761890                }
  • trunk/src/libs/xpcom18a4/python/src/TypeObject.cpp

    r64330 r86333  
    5252
    5353
     54#ifndef Py_LIMITED_API
    5455static PyTypeObject PyInterfaceType_Type = {
    5556        PyVarObject_HEAD_INIT(&PyType_Type, 0)
     
    7677};
    7778
     79#else  /* Py_LIMITED_API */
     80
     81/** The offset of PyTypeObject::ob_name. */
     82static size_t g_offObTypeNameMember = sizeof(PyVarObject);
     83
     84/**
     85 * Base type object for XPCOM interfaces.  Created dynamicially.
     86 */
     87static PyTypeObject *g_pPyInterfaceTypeObj = NULL;
     88
     89/**
     90 * Gets the base XPCOM interface type object, creating it if needed.
     91 */
     92static PyTypeObject *PyXPCOM_GetInterfaceType(void)
     93{
     94        PyTypeObject *pTypeObj = g_pPyInterfaceTypeObj;
     95        if (pTypeObj)
     96                return pTypeObj;
     97
     98        static char g_szTypeDoc[] = "Define the behavior of a PythonCOM Interface type."; /* need non-const */
     99        PyType_Slot aTypeSlots[] = {
     100                { Py_tp_doc,            g_szTypeDoc },
     101                { 0, NULL } /* terminator */
     102        };
     103        PyType_Spec TypeSpec = {
     104                /* .name: */            "interface-type",
     105                /* .basicsize: */       0,
     106                /* .itemsize: */        0,
     107                /* .flags: */           Py_TPFLAGS_BASETYPE,
     108                /* .slots: */           aTypeSlots,
     109        };
     110
     111        PyObject *exc_typ = NULL, *exc_val = NULL, *exc_tb = NULL;
     112        PyErr_Fetch(&exc_typ, &exc_val, &exc_tb); /* goes south in PyType_Ready if we don't clear exceptions first. */
     113
     114        pTypeObj = (PyTypeObject *)PyType_FromSpec(&TypeSpec);
     115        assert(pTypeObj);
     116
     117        PyErr_Restore(exc_typ, exc_val, exc_tb);
     118        g_pPyInterfaceTypeObj = pTypeObj;
     119
     120        /*
     121         * Verify/correct g_offObTypeNameMember.
     122         */
     123        /** @todo (could use pipe+read to safely probe memory) */
     124
     125        return pTypeObj;
     126}
     127
     128/**
     129 * Get the PyTypeObject::ob_name value.
     130 *
     131 * @todo This is _horrible_, but there appears to be no simple tp_name getters
     132 *       till https://bugs.python.org/issue31497 (2017).
     133 */
     134const char *PyXPCOMGetObTypeName(PyTypeObject *pTypeObj)
     135{
     136        return *(const char **)((uintptr_t)(pTypeObj) + g_offObTypeNameMember);
     137}
     138
     139#endif /* Py_LIMITED_API */
     140
    78141/*static*/ PRBool
    79142PyXPCOM_TypeObject::IsType(PyTypeObject *t)
     
    81144#if PY_MAJOR_VERSION <= 2
    82145        return t->ob_type == &PyInterfaceType_Type;
    83 #else
     146#elif !defined(Py_LIMITED_API)
    84147        return Py_TYPE(t) == &PyInterfaceType_Type;
     148#else
     149        return Py_TYPE(t) == g_pPyInterfaceTypeObj         /* Typically not the case as t->ob_type is &PyType_Type */
     150            || PyType_IsSubtype(t, g_pPyInterfaceTypeObj); /* rather than g_pPyInterfaceTypeObj because of PyType_FromSpec(). */
    85151#endif
    86152}
     
    241307PyXPCOM_TypeObject::PyXPCOM_TypeObject( const char *name, PyXPCOM_TypeObject *pBase, int typeSize, struct PyMethodDef* methodList, PyXPCOM_I_CTOR thector)
    242308{
     309#ifndef Py_LIMITED_API
    243310        static const PyTypeObject type_template = {
    244311                PyVarObject_HEAD_INIT(&PyInterfaceType_Type, 0)
     
    280347
    281348        *((PyTypeObject *)this) = type_template;
     349#else  /* Py_LIMITED_API */
     350        /* Create the type specs: */
     351        PyType_Slot aTypeSlots[] = {
     352                { Py_tp_base,           PyXPCOM_GetInterfaceType() },
     353                { Py_tp_dealloc,        (void *)(uintptr_t)&PyXPCOM_TypeObject::Py_dealloc },
     354                { Py_tp_getattr,        (void *)(uintptr_t)&PyXPCOM_TypeObject::Py_getattr },
     355                { Py_tp_setattr,        (void *)(uintptr_t)&PyXPCOM_TypeObject::Py_setattr },
     356                { Py_tp_repr,           (void *)(uintptr_t)&PyXPCOM_TypeObject::Py_repr },
     357                { Py_tp_hash,           (void *)(uintptr_t)&PyXPCOM_TypeObject::Py_hash },
     358                { Py_tp_str,            (void *)(uintptr_t)&PyXPCOM_TypeObject::Py_str },
     359                { Py_tp_richcompare,    (void *)(uintptr_t)&PyXPCOM_TypeObject::Py_richcmp },
     360                { 0, NULL } /* terminator */
     361        };
     362        PyType_Spec TypeSpec = {
     363                /* .name: */            name,
     364                /* .basicsize: */       typeSize,
     365                /* .itemsize: */        0,
     366                /* .flags: */           Py_TPFLAGS_BASETYPE /*?*/,
     367                /* .slots: */           aTypeSlots,
     368        };
     369
     370        PyObject *exc_typ = NULL, *exc_val = NULL, *exc_tb = NULL;
     371        PyErr_Fetch(&exc_typ, &exc_val, &exc_tb); /* goes south in PyType_Ready if we don't clear exceptions first. */
     372
     373        m_pTypeObj = (PyTypeObject *)PyType_FromSpec(&TypeSpec);
     374        assert(m_pTypeObj);
     375
     376        PyErr_Restore(exc_typ, exc_val, exc_tb);
     377
     378        /* Initialize the PyObject part - needed so we can keep instance in a PyDict: */
     379        ob_type = PyXPCOM_GetInterfaceType();
     380        _Py_NewReference(this);
     381
     382#endif /* Py_LIMITED_API */
    282383
    283384        chain.methods = methodList;
     
    287388        ctor = thector;
    288389
     390#ifndef Py_LIMITED_API
    289391        // cast away const, as Python doesnt use it.
    290392        tp_name = (char *)name;
    291393        tp_basicsize = typeSize;
     394#endif
    292395}
    293396
     
    295398{
    296399}
     400
  • trunk/src/libs/xpcom18a4/python/src/VariantUtils.cpp

    r86309 r86333  
    498498                                NS_ABORT_IF_FALSE(PyUnicode_Check(val_use), "PyUnicode_FromObject didnt return a Unicode object!");
    499499                                // Lossy!
     500#ifndef Py_LIMITED_API
    500501                                FILL_SIMPLE_POINTER( PRUnichar, *PyUnicode_AS_UNICODE(val_use) );
     502#else
     503                                FILL_SIMPLE_POINTER( PRUnichar, PyUnicode_ReadChar(val_use, 0) );
     504#endif
    501505                                break;
    502506
     
    833837#endif
    834838                                nr = v->SetAsWStringWithSize(0, (PRUnichar*)NULL);
    835                         } else {
     839                        }
     840                        else {
    836841                                PRUint32 nch;
    837842                                PRUnichar *p;
    838843                                if (PyUnicode_AsPRUnichar(ob, &p, &nch) < 0) {
    839                                         PyXPCOM_LogWarning("Failed to convert object to unicode", ob->ob_type->tp_name);
     844                                        PyXPCOM_LogWarning("Failed to convert object to unicode", PyXPCOM_ObTypeName(ob));
    840845                                        nr = NS_ERROR_UNEXPECTED;
    841846                                        break;
     
    894899                        break;
    895900                case (PRUint16)-1:
    896                         PyXPCOM_LogWarning("Objects of type '%s' can not be converted to an nsIVariant", ob->ob_type->tp_name);
     901                        PyXPCOM_LogWarning("Objects of type '%s' can not be converted to an nsIVariant", PyXPCOM_ObTypeName(ob));
    897902                        nr = NS_ERROR_UNEXPECTED;
    898903                default:
    899904                        NS_ABORT_IF_FALSE(0, "BestVariantTypeForPyObject() returned a variant type not handled here!");
    900                         PyXPCOM_LogWarning("Objects of type '%s' can not be converted to an nsIVariant", ob->ob_type->tp_name);
     905                        PyXPCOM_LogWarning("Objects of type '%s' can not be converted to an nsIVariant", PyXPCOM_ObTypeName(ob));
    901906                        nr = NS_ERROR_UNEXPECTED;
    902907        }
     
    14241429                        }
    14251430
     1431# ifndef Py_LIMITED_API
    14261432                        ns_v.val.c = *PyUnicode_AS_UNICODE(val_use);
     1433# else
     1434                        ns_v.val.c = PyUnicode_ReadChar(val_use, 0);
     1435# endif
    14271436#endif
    14281437                        break;
     
    14501459                        }
    14511460                        // Lossy!
     1461#ifndef Py_LIMITED_API
    14521462                        ns_v.val.wc = *PyUnicode_AS_UNICODE(val_use);
     1463#else
     1464                        ns_v.val.wc = PyUnicode_ReadChar(val_use, 0);
     1465#endif
    14531466                        break;
    14541467                        }
     
    25682581                        BREAK_FALSE;
    25692582                }
     2583# ifndef Py_LIMITED_API
    25702584                FILL_SIMPLE_POINTER( char, *PyUnicode_AS_UNICODE(val) );
     2585# else
     2586                FILL_SIMPLE_POINTER( char, PyUnicode_ReadChar(val, 0) );
     2587# endif
    25712588#endif
    25722589                break;
     
    25882605                NS_ABORT_IF_FALSE(PyUnicode_Check(val_use), "PyUnicode_FromObject didnt return a Unicode object!");
    25892606                // Lossy!
     2607#ifndef Py_LIMITED_API
    25902608                FILL_SIMPLE_POINTER( PRUnichar, *PyUnicode_AS_UNICODE(val_use) );
     2609#else
     2610                FILL_SIMPLE_POINTER( PRUnichar, PyUnicode_ReadChar(val_use, 0) );
     2611#endif
    25912612                break;
    25922613
     
    29312952                if (val != Py_None) {
    29322953                        if (!PySequence_Check(val)) {
    2933                                 PyErr_Format(PyExc_TypeError, "Object for xpcom array must be a sequence, not type '%s'", val->ob_type->tp_name);
     2954                                PyErr_Format(PyExc_TypeError, "Object for xpcom array must be a sequence, not type '%s'", PyXPCOM_ObTypeName(val));
    29342955                                BREAK_FALSE;
    29352956                        }
  • trunk/src/libs/xpcom18a4/python/src/module/_xpcom.cpp

    r69588 r86333  
    132132#  endif
    133133# else
    134 #  define MODULE_NAME     MANGLE_MODULE_NAME("VBoxPython")
    135134#  if PY_MAJOR_VERSION <= 2
    136 #   define initVBoxPython  MANGLE_MODULE_INIT(initVBoxPython)
     135#   define MODULE_NAME    MANGLE_MODULE_NAME("VBoxPython")
     136#   define initVBoxPython MANGLE_MODULE_INIT(initVBoxPython)
     137#  elif defined(Py_LIMITED_API)
     138#   define MODULE_NAME    MANGLE_MODULE_NAME("VBoxPython3")
     139#   define initVBoxPython MANGLE_MODULE_INIT(PyInit_VBoxPython3)
    137140#  else
    138 #   define initVBoxPython  MANGLE_MODULE_INIT(PyInit_VBoxPython)
     141#   define MODULE_NAME    MANGLE_MODULE_NAME("VBoxPython")
     142#   define initVBoxPython MANGLE_MODULE_INIT(PyInit_VBoxPython)
    139143#  endif
    140144# endif
     
    271275                return PyErr_Format(PyExc_TypeError,
    272276                                    "First param must be a native nsISupports wrapper (got %s)",
    273                                     obIS->ob_type->tp_name);
     277                                    PyXPCOM_ObTypeName(obIS));
    274278        }
    275279        // Ack!  We must ask for the "native" interface supported by
     
    497501                return PyErr_Format(PyExc_ValueError,
    498502                                    "Object is not an nsIVariant (got %s)",
    499                                     ob->ob_type->tp_name);
     503                                    PyXPCOM_ObTypeName(ob));
    500504
    501505        Py_nsISupports *parent = nsnull;
     
    809813#endif
    810814        }
     815#ifndef Py_LIMITED_API
    811816        PyDict_SetItemString(dict, "IIDType", (PyObject *)&Py_nsIID::type);
     817#else
     818        PyDict_SetItemString(dict, "IIDType", (PyObject *)Py_nsIID::GetTypeObject());
     819#endif
    812820
    813821        REGISTER_IID(nsISupports);
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette