123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324 |
- /* Wrap void * pointers to be passed between C modules */
- #include "Python.h"
- /* Internal structure of PyCapsule */
- typedef struct {
- PyObject_HEAD
- void *pointer;
- const char *name;
- void *context;
- PyCapsule_Destructor destructor;
- } PyCapsule;
- static int
- _is_legal_capsule(PyCapsule *capsule, const char *invalid_capsule)
- {
- if (!capsule || !PyCapsule_CheckExact(capsule) || capsule->pointer == NULL) {
- PyErr_SetString(PyExc_ValueError, invalid_capsule);
- return 0;
- }
- return 1;
- }
- #define is_legal_capsule(capsule, name) \
- (_is_legal_capsule(capsule, \
- name " called with invalid PyCapsule object"))
- static int
- name_matches(const char *name1, const char *name2) {
- /* if either is NULL, */
- if (!name1 || !name2) {
- /* they're only the same if they're both NULL. */
- return name1 == name2;
- }
- return !strcmp(name1, name2);
- }
- PyObject *
- PyCapsule_New(void *pointer, const char *name, PyCapsule_Destructor destructor)
- {
- PyCapsule *capsule;
- if (!pointer) {
- PyErr_SetString(PyExc_ValueError, "PyCapsule_New called with null pointer");
- return NULL;
- }
- capsule = PyObject_New(PyCapsule, &PyCapsule_Type);
- if (capsule == NULL) {
- return NULL;
- }
- capsule->pointer = pointer;
- capsule->name = name;
- capsule->context = NULL;
- capsule->destructor = destructor;
- return (PyObject *)capsule;
- }
- int
- PyCapsule_IsValid(PyObject *o, const char *name)
- {
- PyCapsule *capsule = (PyCapsule *)o;
- return (capsule != NULL &&
- PyCapsule_CheckExact(capsule) &&
- capsule->pointer != NULL &&
- name_matches(capsule->name, name));
- }
- void *
- PyCapsule_GetPointer(PyObject *o, const char *name)
- {
- PyCapsule *capsule = (PyCapsule *)o;
- if (!is_legal_capsule(capsule, "PyCapsule_GetPointer")) {
- return NULL;
- }
- if (!name_matches(name, capsule->name)) {
- PyErr_SetString(PyExc_ValueError, "PyCapsule_GetPointer called with incorrect name");
- return NULL;
- }
- return capsule->pointer;
- }
- const char *
- PyCapsule_GetName(PyObject *o)
- {
- PyCapsule *capsule = (PyCapsule *)o;
- if (!is_legal_capsule(capsule, "PyCapsule_GetName")) {
- return NULL;
- }
- return capsule->name;
- }
- PyCapsule_Destructor
- PyCapsule_GetDestructor(PyObject *o)
- {
- PyCapsule *capsule = (PyCapsule *)o;
- if (!is_legal_capsule(capsule, "PyCapsule_GetDestructor")) {
- return NULL;
- }
- return capsule->destructor;
- }
- void *
- PyCapsule_GetContext(PyObject *o)
- {
- PyCapsule *capsule = (PyCapsule *)o;
- if (!is_legal_capsule(capsule, "PyCapsule_GetContext")) {
- return NULL;
- }
- return capsule->context;
- }
- int
- PyCapsule_SetPointer(PyObject *o, void *pointer)
- {
- PyCapsule *capsule = (PyCapsule *)o;
- if (!pointer) {
- PyErr_SetString(PyExc_ValueError, "PyCapsule_SetPointer called with null pointer");
- return -1;
- }
- if (!is_legal_capsule(capsule, "PyCapsule_SetPointer")) {
- return -1;
- }
- capsule->pointer = pointer;
- return 0;
- }
- int
- PyCapsule_SetName(PyObject *o, const char *name)
- {
- PyCapsule *capsule = (PyCapsule *)o;
- if (!is_legal_capsule(capsule, "PyCapsule_SetName")) {
- return -1;
- }
- capsule->name = name;
- return 0;
- }
- int
- PyCapsule_SetDestructor(PyObject *o, PyCapsule_Destructor destructor)
- {
- PyCapsule *capsule = (PyCapsule *)o;
- if (!is_legal_capsule(capsule, "PyCapsule_SetDestructor")) {
- return -1;
- }
- capsule->destructor = destructor;
- return 0;
- }
- int
- PyCapsule_SetContext(PyObject *o, void *context)
- {
- PyCapsule *capsule = (PyCapsule *)o;
- if (!is_legal_capsule(capsule, "PyCapsule_SetContext")) {
- return -1;
- }
- capsule->context = context;
- return 0;
- }
- void *
- PyCapsule_Import(const char *name, int no_block)
- {
- PyObject *object = NULL;
- void *return_value = NULL;
- char *trace;
- #if defined(__has_feature)
- # if __has_feature(memory_sanitizer)
- __msan_unpoison_string(name);
- # endif
- #endif
- size_t name_length = (strlen(name) + 1) * sizeof(char);
- char *name_dup = (char *)PyMem_Malloc(name_length);
- if (!name_dup) {
- return PyErr_NoMemory();
- }
- memcpy(name_dup, name, name_length);
- trace = name_dup;
- while (trace) {
- char *dot = strchr(trace, '.');
- if (dot) {
- *dot++ = '\0';
- }
- if (object == NULL) {
- object = PyImport_ImportModule(trace);
- if (!object) {
- PyErr_Format(PyExc_ImportError, "PyCapsule_Import could not import module \"%s\"", trace);
- }
- } else {
- PyObject *object2 = PyObject_GetAttrString(object, trace);
- Py_SETREF(object, object2);
- }
- if (!object) {
- goto EXIT;
- }
- trace = dot;
- }
- /* compare attribute name to module.name by hand */
- if (PyCapsule_IsValid(object, name)) {
- PyCapsule *capsule = (PyCapsule *)object;
- return_value = capsule->pointer;
- } else {
- PyErr_Format(PyExc_AttributeError,
- "PyCapsule_Import \"%s\" is not valid",
- name);
- }
- EXIT:
- Py_XDECREF(object);
- if (name_dup) {
- PyMem_Free(name_dup);
- }
- return return_value;
- }
- static void
- capsule_dealloc(PyObject *o)
- {
- PyCapsule *capsule = (PyCapsule *)o;
- if (capsule->destructor) {
- capsule->destructor(o);
- }
- PyObject_Free(o);
- }
- static PyObject *
- capsule_repr(PyObject *o)
- {
- PyCapsule *capsule = (PyCapsule *)o;
- const char *name;
- const char *quote;
- if (capsule->name) {
- quote = "\"";
- name = capsule->name;
- } else {
- quote = "";
- name = "NULL";
- }
- return PyUnicode_FromFormat("<capsule object %s%s%s at %p>",
- quote, name, quote, capsule);
- }
- PyDoc_STRVAR(PyCapsule_Type__doc__,
- "Capsule objects let you wrap a C \"void *\" pointer in a Python\n\
- object. They're a way of passing data through the Python interpreter\n\
- without creating your own custom type.\n\
- \n\
- Capsules are used for communication between extension modules.\n\
- They provide a way for an extension module to export a C interface\n\
- to other extension modules, so that extension modules can use the\n\
- Python import mechanism to link to one another.\n\
- ");
- PyTypeObject PyCapsule_Type = {
- PyVarObject_HEAD_INIT(&PyType_Type, 0)
- "PyCapsule", /*tp_name*/
- sizeof(PyCapsule), /*tp_basicsize*/
- 0, /*tp_itemsize*/
- /* methods */
- capsule_dealloc, /*tp_dealloc*/
- 0, /*tp_vectorcall_offset*/
- 0, /*tp_getattr*/
- 0, /*tp_setattr*/
- 0, /*tp_as_async*/
- capsule_repr, /*tp_repr*/
- 0, /*tp_as_number*/
- 0, /*tp_as_sequence*/
- 0, /*tp_as_mapping*/
- 0, /*tp_hash*/
- 0, /*tp_call*/
- 0, /*tp_str*/
- 0, /*tp_getattro*/
- 0, /*tp_setattro*/
- 0, /*tp_as_buffer*/
- 0, /*tp_flags*/
- PyCapsule_Type__doc__ /*tp_doc*/
- };
|