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