17db96d56Sopenharmony_ci/* Wrap void * pointers to be passed between C modules */
27db96d56Sopenharmony_ci
37db96d56Sopenharmony_ci#include "Python.h"
47db96d56Sopenharmony_ci
57db96d56Sopenharmony_ci/* Internal structure of PyCapsule */
67db96d56Sopenharmony_citypedef struct {
77db96d56Sopenharmony_ci    PyObject_HEAD
87db96d56Sopenharmony_ci    void *pointer;
97db96d56Sopenharmony_ci    const char *name;
107db96d56Sopenharmony_ci    void *context;
117db96d56Sopenharmony_ci    PyCapsule_Destructor destructor;
127db96d56Sopenharmony_ci} PyCapsule;
137db96d56Sopenharmony_ci
147db96d56Sopenharmony_ci
157db96d56Sopenharmony_ci
167db96d56Sopenharmony_cistatic int
177db96d56Sopenharmony_ci_is_legal_capsule(PyCapsule *capsule, const char *invalid_capsule)
187db96d56Sopenharmony_ci{
197db96d56Sopenharmony_ci    if (!capsule || !PyCapsule_CheckExact(capsule) || capsule->pointer == NULL) {
207db96d56Sopenharmony_ci        PyErr_SetString(PyExc_ValueError, invalid_capsule);
217db96d56Sopenharmony_ci        return 0;
227db96d56Sopenharmony_ci    }
237db96d56Sopenharmony_ci    return 1;
247db96d56Sopenharmony_ci}
257db96d56Sopenharmony_ci
267db96d56Sopenharmony_ci#define is_legal_capsule(capsule, name) \
277db96d56Sopenharmony_ci    (_is_legal_capsule(capsule, \
287db96d56Sopenharmony_ci     name " called with invalid PyCapsule object"))
297db96d56Sopenharmony_ci
307db96d56Sopenharmony_ci
317db96d56Sopenharmony_cistatic int
327db96d56Sopenharmony_ciname_matches(const char *name1, const char *name2) {
337db96d56Sopenharmony_ci    /* if either is NULL, */
347db96d56Sopenharmony_ci    if (!name1 || !name2) {
357db96d56Sopenharmony_ci        /* they're only the same if they're both NULL. */
367db96d56Sopenharmony_ci        return name1 == name2;
377db96d56Sopenharmony_ci    }
387db96d56Sopenharmony_ci    return !strcmp(name1, name2);
397db96d56Sopenharmony_ci}
407db96d56Sopenharmony_ci
417db96d56Sopenharmony_ci
427db96d56Sopenharmony_ci
437db96d56Sopenharmony_ciPyObject *
447db96d56Sopenharmony_ciPyCapsule_New(void *pointer, const char *name, PyCapsule_Destructor destructor)
457db96d56Sopenharmony_ci{
467db96d56Sopenharmony_ci    PyCapsule *capsule;
477db96d56Sopenharmony_ci
487db96d56Sopenharmony_ci    if (!pointer) {
497db96d56Sopenharmony_ci        PyErr_SetString(PyExc_ValueError, "PyCapsule_New called with null pointer");
507db96d56Sopenharmony_ci        return NULL;
517db96d56Sopenharmony_ci    }
527db96d56Sopenharmony_ci
537db96d56Sopenharmony_ci    capsule = PyObject_New(PyCapsule, &PyCapsule_Type);
547db96d56Sopenharmony_ci    if (capsule == NULL) {
557db96d56Sopenharmony_ci        return NULL;
567db96d56Sopenharmony_ci    }
577db96d56Sopenharmony_ci
587db96d56Sopenharmony_ci    capsule->pointer = pointer;
597db96d56Sopenharmony_ci    capsule->name = name;
607db96d56Sopenharmony_ci    capsule->context = NULL;
617db96d56Sopenharmony_ci    capsule->destructor = destructor;
627db96d56Sopenharmony_ci
637db96d56Sopenharmony_ci    return (PyObject *)capsule;
647db96d56Sopenharmony_ci}
657db96d56Sopenharmony_ci
667db96d56Sopenharmony_ci
677db96d56Sopenharmony_ciint
687db96d56Sopenharmony_ciPyCapsule_IsValid(PyObject *o, const char *name)
697db96d56Sopenharmony_ci{
707db96d56Sopenharmony_ci    PyCapsule *capsule = (PyCapsule *)o;
717db96d56Sopenharmony_ci
727db96d56Sopenharmony_ci    return (capsule != NULL &&
737db96d56Sopenharmony_ci            PyCapsule_CheckExact(capsule) &&
747db96d56Sopenharmony_ci            capsule->pointer != NULL &&
757db96d56Sopenharmony_ci            name_matches(capsule->name, name));
767db96d56Sopenharmony_ci}
777db96d56Sopenharmony_ci
787db96d56Sopenharmony_ci
797db96d56Sopenharmony_civoid *
807db96d56Sopenharmony_ciPyCapsule_GetPointer(PyObject *o, const char *name)
817db96d56Sopenharmony_ci{
827db96d56Sopenharmony_ci    PyCapsule *capsule = (PyCapsule *)o;
837db96d56Sopenharmony_ci
847db96d56Sopenharmony_ci    if (!is_legal_capsule(capsule, "PyCapsule_GetPointer")) {
857db96d56Sopenharmony_ci        return NULL;
867db96d56Sopenharmony_ci    }
877db96d56Sopenharmony_ci
887db96d56Sopenharmony_ci    if (!name_matches(name, capsule->name)) {
897db96d56Sopenharmony_ci        PyErr_SetString(PyExc_ValueError, "PyCapsule_GetPointer called with incorrect name");
907db96d56Sopenharmony_ci        return NULL;
917db96d56Sopenharmony_ci    }
927db96d56Sopenharmony_ci
937db96d56Sopenharmony_ci    return capsule->pointer;
947db96d56Sopenharmony_ci}
957db96d56Sopenharmony_ci
967db96d56Sopenharmony_ci
977db96d56Sopenharmony_ciconst char *
987db96d56Sopenharmony_ciPyCapsule_GetName(PyObject *o)
997db96d56Sopenharmony_ci{
1007db96d56Sopenharmony_ci    PyCapsule *capsule = (PyCapsule *)o;
1017db96d56Sopenharmony_ci
1027db96d56Sopenharmony_ci    if (!is_legal_capsule(capsule, "PyCapsule_GetName")) {
1037db96d56Sopenharmony_ci        return NULL;
1047db96d56Sopenharmony_ci    }
1057db96d56Sopenharmony_ci    return capsule->name;
1067db96d56Sopenharmony_ci}
1077db96d56Sopenharmony_ci
1087db96d56Sopenharmony_ci
1097db96d56Sopenharmony_ciPyCapsule_Destructor
1107db96d56Sopenharmony_ciPyCapsule_GetDestructor(PyObject *o)
1117db96d56Sopenharmony_ci{
1127db96d56Sopenharmony_ci    PyCapsule *capsule = (PyCapsule *)o;
1137db96d56Sopenharmony_ci
1147db96d56Sopenharmony_ci    if (!is_legal_capsule(capsule, "PyCapsule_GetDestructor")) {
1157db96d56Sopenharmony_ci        return NULL;
1167db96d56Sopenharmony_ci    }
1177db96d56Sopenharmony_ci    return capsule->destructor;
1187db96d56Sopenharmony_ci}
1197db96d56Sopenharmony_ci
1207db96d56Sopenharmony_ci
1217db96d56Sopenharmony_civoid *
1227db96d56Sopenharmony_ciPyCapsule_GetContext(PyObject *o)
1237db96d56Sopenharmony_ci{
1247db96d56Sopenharmony_ci    PyCapsule *capsule = (PyCapsule *)o;
1257db96d56Sopenharmony_ci
1267db96d56Sopenharmony_ci    if (!is_legal_capsule(capsule, "PyCapsule_GetContext")) {
1277db96d56Sopenharmony_ci        return NULL;
1287db96d56Sopenharmony_ci    }
1297db96d56Sopenharmony_ci    return capsule->context;
1307db96d56Sopenharmony_ci}
1317db96d56Sopenharmony_ci
1327db96d56Sopenharmony_ci
1337db96d56Sopenharmony_ciint
1347db96d56Sopenharmony_ciPyCapsule_SetPointer(PyObject *o, void *pointer)
1357db96d56Sopenharmony_ci{
1367db96d56Sopenharmony_ci    PyCapsule *capsule = (PyCapsule *)o;
1377db96d56Sopenharmony_ci
1387db96d56Sopenharmony_ci    if (!pointer) {
1397db96d56Sopenharmony_ci        PyErr_SetString(PyExc_ValueError, "PyCapsule_SetPointer called with null pointer");
1407db96d56Sopenharmony_ci        return -1;
1417db96d56Sopenharmony_ci    }
1427db96d56Sopenharmony_ci
1437db96d56Sopenharmony_ci    if (!is_legal_capsule(capsule, "PyCapsule_SetPointer")) {
1447db96d56Sopenharmony_ci        return -1;
1457db96d56Sopenharmony_ci    }
1467db96d56Sopenharmony_ci
1477db96d56Sopenharmony_ci    capsule->pointer = pointer;
1487db96d56Sopenharmony_ci    return 0;
1497db96d56Sopenharmony_ci}
1507db96d56Sopenharmony_ci
1517db96d56Sopenharmony_ci
1527db96d56Sopenharmony_ciint
1537db96d56Sopenharmony_ciPyCapsule_SetName(PyObject *o, const char *name)
1547db96d56Sopenharmony_ci{
1557db96d56Sopenharmony_ci    PyCapsule *capsule = (PyCapsule *)o;
1567db96d56Sopenharmony_ci
1577db96d56Sopenharmony_ci    if (!is_legal_capsule(capsule, "PyCapsule_SetName")) {
1587db96d56Sopenharmony_ci        return -1;
1597db96d56Sopenharmony_ci    }
1607db96d56Sopenharmony_ci
1617db96d56Sopenharmony_ci    capsule->name = name;
1627db96d56Sopenharmony_ci    return 0;
1637db96d56Sopenharmony_ci}
1647db96d56Sopenharmony_ci
1657db96d56Sopenharmony_ci
1667db96d56Sopenharmony_ciint
1677db96d56Sopenharmony_ciPyCapsule_SetDestructor(PyObject *o, PyCapsule_Destructor destructor)
1687db96d56Sopenharmony_ci{
1697db96d56Sopenharmony_ci    PyCapsule *capsule = (PyCapsule *)o;
1707db96d56Sopenharmony_ci
1717db96d56Sopenharmony_ci    if (!is_legal_capsule(capsule, "PyCapsule_SetDestructor")) {
1727db96d56Sopenharmony_ci        return -1;
1737db96d56Sopenharmony_ci    }
1747db96d56Sopenharmony_ci
1757db96d56Sopenharmony_ci    capsule->destructor = destructor;
1767db96d56Sopenharmony_ci    return 0;
1777db96d56Sopenharmony_ci}
1787db96d56Sopenharmony_ci
1797db96d56Sopenharmony_ci
1807db96d56Sopenharmony_ciint
1817db96d56Sopenharmony_ciPyCapsule_SetContext(PyObject *o, void *context)
1827db96d56Sopenharmony_ci{
1837db96d56Sopenharmony_ci    PyCapsule *capsule = (PyCapsule *)o;
1847db96d56Sopenharmony_ci
1857db96d56Sopenharmony_ci    if (!is_legal_capsule(capsule, "PyCapsule_SetContext")) {
1867db96d56Sopenharmony_ci        return -1;
1877db96d56Sopenharmony_ci    }
1887db96d56Sopenharmony_ci
1897db96d56Sopenharmony_ci    capsule->context = context;
1907db96d56Sopenharmony_ci    return 0;
1917db96d56Sopenharmony_ci}
1927db96d56Sopenharmony_ci
1937db96d56Sopenharmony_ci
1947db96d56Sopenharmony_civoid *
1957db96d56Sopenharmony_ciPyCapsule_Import(const char *name, int no_block)
1967db96d56Sopenharmony_ci{
1977db96d56Sopenharmony_ci    PyObject *object = NULL;
1987db96d56Sopenharmony_ci    void *return_value = NULL;
1997db96d56Sopenharmony_ci    char *trace;
2007db96d56Sopenharmony_ci    size_t name_length = (strlen(name) + 1) * sizeof(char);
2017db96d56Sopenharmony_ci    char *name_dup = (char *)PyMem_Malloc(name_length);
2027db96d56Sopenharmony_ci
2037db96d56Sopenharmony_ci    if (!name_dup) {
2047db96d56Sopenharmony_ci        return PyErr_NoMemory();
2057db96d56Sopenharmony_ci    }
2067db96d56Sopenharmony_ci
2077db96d56Sopenharmony_ci    memcpy(name_dup, name, name_length);
2087db96d56Sopenharmony_ci
2097db96d56Sopenharmony_ci    trace = name_dup;
2107db96d56Sopenharmony_ci    while (trace) {
2117db96d56Sopenharmony_ci        char *dot = strchr(trace, '.');
2127db96d56Sopenharmony_ci        if (dot) {
2137db96d56Sopenharmony_ci            *dot++ = '\0';
2147db96d56Sopenharmony_ci        }
2157db96d56Sopenharmony_ci
2167db96d56Sopenharmony_ci        if (object == NULL) {
2177db96d56Sopenharmony_ci            object = PyImport_ImportModule(trace);
2187db96d56Sopenharmony_ci            if (!object) {
2197db96d56Sopenharmony_ci                PyErr_Format(PyExc_ImportError, "PyCapsule_Import could not import module \"%s\"", trace);
2207db96d56Sopenharmony_ci            }
2217db96d56Sopenharmony_ci        } else {
2227db96d56Sopenharmony_ci            PyObject *object2 = PyObject_GetAttrString(object, trace);
2237db96d56Sopenharmony_ci            Py_DECREF(object);
2247db96d56Sopenharmony_ci            object = object2;
2257db96d56Sopenharmony_ci        }
2267db96d56Sopenharmony_ci        if (!object) {
2277db96d56Sopenharmony_ci            goto EXIT;
2287db96d56Sopenharmony_ci        }
2297db96d56Sopenharmony_ci
2307db96d56Sopenharmony_ci        trace = dot;
2317db96d56Sopenharmony_ci    }
2327db96d56Sopenharmony_ci
2337db96d56Sopenharmony_ci    /* compare attribute name to module.name by hand */
2347db96d56Sopenharmony_ci    if (PyCapsule_IsValid(object, name)) {
2357db96d56Sopenharmony_ci        PyCapsule *capsule = (PyCapsule *)object;
2367db96d56Sopenharmony_ci        return_value = capsule->pointer;
2377db96d56Sopenharmony_ci    } else {
2387db96d56Sopenharmony_ci        PyErr_Format(PyExc_AttributeError,
2397db96d56Sopenharmony_ci            "PyCapsule_Import \"%s\" is not valid",
2407db96d56Sopenharmony_ci            name);
2417db96d56Sopenharmony_ci    }
2427db96d56Sopenharmony_ci
2437db96d56Sopenharmony_ciEXIT:
2447db96d56Sopenharmony_ci    Py_XDECREF(object);
2457db96d56Sopenharmony_ci    if (name_dup) {
2467db96d56Sopenharmony_ci        PyMem_Free(name_dup);
2477db96d56Sopenharmony_ci    }
2487db96d56Sopenharmony_ci    return return_value;
2497db96d56Sopenharmony_ci}
2507db96d56Sopenharmony_ci
2517db96d56Sopenharmony_ci
2527db96d56Sopenharmony_cistatic void
2537db96d56Sopenharmony_cicapsule_dealloc(PyObject *o)
2547db96d56Sopenharmony_ci{
2557db96d56Sopenharmony_ci    PyCapsule *capsule = (PyCapsule *)o;
2567db96d56Sopenharmony_ci    if (capsule->destructor) {
2577db96d56Sopenharmony_ci        capsule->destructor(o);
2587db96d56Sopenharmony_ci    }
2597db96d56Sopenharmony_ci    PyObject_Free(o);
2607db96d56Sopenharmony_ci}
2617db96d56Sopenharmony_ci
2627db96d56Sopenharmony_ci
2637db96d56Sopenharmony_cistatic PyObject *
2647db96d56Sopenharmony_cicapsule_repr(PyObject *o)
2657db96d56Sopenharmony_ci{
2667db96d56Sopenharmony_ci    PyCapsule *capsule = (PyCapsule *)o;
2677db96d56Sopenharmony_ci    const char *name;
2687db96d56Sopenharmony_ci    const char *quote;
2697db96d56Sopenharmony_ci
2707db96d56Sopenharmony_ci    if (capsule->name) {
2717db96d56Sopenharmony_ci        quote = "\"";
2727db96d56Sopenharmony_ci        name = capsule->name;
2737db96d56Sopenharmony_ci    } else {
2747db96d56Sopenharmony_ci        quote = "";
2757db96d56Sopenharmony_ci        name = "NULL";
2767db96d56Sopenharmony_ci    }
2777db96d56Sopenharmony_ci
2787db96d56Sopenharmony_ci    return PyUnicode_FromFormat("<capsule object %s%s%s at %p>",
2797db96d56Sopenharmony_ci        quote, name, quote, capsule);
2807db96d56Sopenharmony_ci}
2817db96d56Sopenharmony_ci
2827db96d56Sopenharmony_ci
2837db96d56Sopenharmony_ci
2847db96d56Sopenharmony_ciPyDoc_STRVAR(PyCapsule_Type__doc__,
2857db96d56Sopenharmony_ci"Capsule objects let you wrap a C \"void *\" pointer in a Python\n\
2867db96d56Sopenharmony_ciobject.  They're a way of passing data through the Python interpreter\n\
2877db96d56Sopenharmony_ciwithout creating your own custom type.\n\
2887db96d56Sopenharmony_ci\n\
2897db96d56Sopenharmony_ciCapsules are used for communication between extension modules.\n\
2907db96d56Sopenharmony_ciThey provide a way for an extension module to export a C interface\n\
2917db96d56Sopenharmony_cito other extension modules, so that extension modules can use the\n\
2927db96d56Sopenharmony_ciPython import mechanism to link to one another.\n\
2937db96d56Sopenharmony_ci");
2947db96d56Sopenharmony_ci
2957db96d56Sopenharmony_ciPyTypeObject PyCapsule_Type = {
2967db96d56Sopenharmony_ci    PyVarObject_HEAD_INIT(&PyType_Type, 0)
2977db96d56Sopenharmony_ci    "PyCapsule",                /*tp_name*/
2987db96d56Sopenharmony_ci    sizeof(PyCapsule),          /*tp_basicsize*/
2997db96d56Sopenharmony_ci    0,                          /*tp_itemsize*/
3007db96d56Sopenharmony_ci    /* methods */
3017db96d56Sopenharmony_ci    capsule_dealloc, /*tp_dealloc*/
3027db96d56Sopenharmony_ci    0,                          /*tp_vectorcall_offset*/
3037db96d56Sopenharmony_ci    0,                          /*tp_getattr*/
3047db96d56Sopenharmony_ci    0,                          /*tp_setattr*/
3057db96d56Sopenharmony_ci    0,                          /*tp_as_async*/
3067db96d56Sopenharmony_ci    capsule_repr, /*tp_repr*/
3077db96d56Sopenharmony_ci    0,                          /*tp_as_number*/
3087db96d56Sopenharmony_ci    0,                          /*tp_as_sequence*/
3097db96d56Sopenharmony_ci    0,                          /*tp_as_mapping*/
3107db96d56Sopenharmony_ci    0,                          /*tp_hash*/
3117db96d56Sopenharmony_ci    0,                          /*tp_call*/
3127db96d56Sopenharmony_ci    0,                          /*tp_str*/
3137db96d56Sopenharmony_ci    0,                          /*tp_getattro*/
3147db96d56Sopenharmony_ci    0,                          /*tp_setattro*/
3157db96d56Sopenharmony_ci    0,                          /*tp_as_buffer*/
3167db96d56Sopenharmony_ci    0,                          /*tp_flags*/
3177db96d56Sopenharmony_ci    PyCapsule_Type__doc__       /*tp_doc*/
3187db96d56Sopenharmony_ci};
3197db96d56Sopenharmony_ci
3207db96d56Sopenharmony_ci
321