xref: /third_party/python/Objects/capsule.c (revision 7db96d56)
1/* Wrap void * pointers to be passed between C modules */
2
3#include "Python.h"
4
5/* Internal structure of PyCapsule */
6typedef struct {
7    PyObject_HEAD
8    void *pointer;
9    const char *name;
10    void *context;
11    PyCapsule_Destructor destructor;
12} PyCapsule;
13
14
15
16static int
17_is_legal_capsule(PyCapsule *capsule, const char *invalid_capsule)
18{
19    if (!capsule || !PyCapsule_CheckExact(capsule) || capsule->pointer == NULL) {
20        PyErr_SetString(PyExc_ValueError, invalid_capsule);
21        return 0;
22    }
23    return 1;
24}
25
26#define is_legal_capsule(capsule, name) \
27    (_is_legal_capsule(capsule, \
28     name " called with invalid PyCapsule object"))
29
30
31static int
32name_matches(const char *name1, const char *name2) {
33    /* if either is NULL, */
34    if (!name1 || !name2) {
35        /* they're only the same if they're both NULL. */
36        return name1 == name2;
37    }
38    return !strcmp(name1, name2);
39}
40
41
42
43PyObject *
44PyCapsule_New(void *pointer, const char *name, PyCapsule_Destructor destructor)
45{
46    PyCapsule *capsule;
47
48    if (!pointer) {
49        PyErr_SetString(PyExc_ValueError, "PyCapsule_New called with null pointer");
50        return NULL;
51    }
52
53    capsule = PyObject_New(PyCapsule, &PyCapsule_Type);
54    if (capsule == NULL) {
55        return NULL;
56    }
57
58    capsule->pointer = pointer;
59    capsule->name = name;
60    capsule->context = NULL;
61    capsule->destructor = destructor;
62
63    return (PyObject *)capsule;
64}
65
66
67int
68PyCapsule_IsValid(PyObject *o, const char *name)
69{
70    PyCapsule *capsule = (PyCapsule *)o;
71
72    return (capsule != NULL &&
73            PyCapsule_CheckExact(capsule) &&
74            capsule->pointer != NULL &&
75            name_matches(capsule->name, name));
76}
77
78
79void *
80PyCapsule_GetPointer(PyObject *o, const char *name)
81{
82    PyCapsule *capsule = (PyCapsule *)o;
83
84    if (!is_legal_capsule(capsule, "PyCapsule_GetPointer")) {
85        return NULL;
86    }
87
88    if (!name_matches(name, capsule->name)) {
89        PyErr_SetString(PyExc_ValueError, "PyCapsule_GetPointer called with incorrect name");
90        return NULL;
91    }
92
93    return capsule->pointer;
94}
95
96
97const char *
98PyCapsule_GetName(PyObject *o)
99{
100    PyCapsule *capsule = (PyCapsule *)o;
101
102    if (!is_legal_capsule(capsule, "PyCapsule_GetName")) {
103        return NULL;
104    }
105    return capsule->name;
106}
107
108
109PyCapsule_Destructor
110PyCapsule_GetDestructor(PyObject *o)
111{
112    PyCapsule *capsule = (PyCapsule *)o;
113
114    if (!is_legal_capsule(capsule, "PyCapsule_GetDestructor")) {
115        return NULL;
116    }
117    return capsule->destructor;
118}
119
120
121void *
122PyCapsule_GetContext(PyObject *o)
123{
124    PyCapsule *capsule = (PyCapsule *)o;
125
126    if (!is_legal_capsule(capsule, "PyCapsule_GetContext")) {
127        return NULL;
128    }
129    return capsule->context;
130}
131
132
133int
134PyCapsule_SetPointer(PyObject *o, void *pointer)
135{
136    PyCapsule *capsule = (PyCapsule *)o;
137
138    if (!pointer) {
139        PyErr_SetString(PyExc_ValueError, "PyCapsule_SetPointer called with null pointer");
140        return -1;
141    }
142
143    if (!is_legal_capsule(capsule, "PyCapsule_SetPointer")) {
144        return -1;
145    }
146
147    capsule->pointer = pointer;
148    return 0;
149}
150
151
152int
153PyCapsule_SetName(PyObject *o, const char *name)
154{
155    PyCapsule *capsule = (PyCapsule *)o;
156
157    if (!is_legal_capsule(capsule, "PyCapsule_SetName")) {
158        return -1;
159    }
160
161    capsule->name = name;
162    return 0;
163}
164
165
166int
167PyCapsule_SetDestructor(PyObject *o, PyCapsule_Destructor destructor)
168{
169    PyCapsule *capsule = (PyCapsule *)o;
170
171    if (!is_legal_capsule(capsule, "PyCapsule_SetDestructor")) {
172        return -1;
173    }
174
175    capsule->destructor = destructor;
176    return 0;
177}
178
179
180int
181PyCapsule_SetContext(PyObject *o, void *context)
182{
183    PyCapsule *capsule = (PyCapsule *)o;
184
185    if (!is_legal_capsule(capsule, "PyCapsule_SetContext")) {
186        return -1;
187    }
188
189    capsule->context = context;
190    return 0;
191}
192
193
194void *
195PyCapsule_Import(const char *name, int no_block)
196{
197    PyObject *object = NULL;
198    void *return_value = NULL;
199    char *trace;
200    size_t name_length = (strlen(name) + 1) * sizeof(char);
201    char *name_dup = (char *)PyMem_Malloc(name_length);
202
203    if (!name_dup) {
204        return PyErr_NoMemory();
205    }
206
207    memcpy(name_dup, name, name_length);
208
209    trace = name_dup;
210    while (trace) {
211        char *dot = strchr(trace, '.');
212        if (dot) {
213            *dot++ = '\0';
214        }
215
216        if (object == NULL) {
217            object = PyImport_ImportModule(trace);
218            if (!object) {
219                PyErr_Format(PyExc_ImportError, "PyCapsule_Import could not import module \"%s\"", trace);
220            }
221        } else {
222            PyObject *object2 = PyObject_GetAttrString(object, trace);
223            Py_DECREF(object);
224            object = object2;
225        }
226        if (!object) {
227            goto EXIT;
228        }
229
230        trace = dot;
231    }
232
233    /* compare attribute name to module.name by hand */
234    if (PyCapsule_IsValid(object, name)) {
235        PyCapsule *capsule = (PyCapsule *)object;
236        return_value = capsule->pointer;
237    } else {
238        PyErr_Format(PyExc_AttributeError,
239            "PyCapsule_Import \"%s\" is not valid",
240            name);
241    }
242
243EXIT:
244    Py_XDECREF(object);
245    if (name_dup) {
246        PyMem_Free(name_dup);
247    }
248    return return_value;
249}
250
251
252static void
253capsule_dealloc(PyObject *o)
254{
255    PyCapsule *capsule = (PyCapsule *)o;
256    if (capsule->destructor) {
257        capsule->destructor(o);
258    }
259    PyObject_Free(o);
260}
261
262
263static PyObject *
264capsule_repr(PyObject *o)
265{
266    PyCapsule *capsule = (PyCapsule *)o;
267    const char *name;
268    const char *quote;
269
270    if (capsule->name) {
271        quote = "\"";
272        name = capsule->name;
273    } else {
274        quote = "";
275        name = "NULL";
276    }
277
278    return PyUnicode_FromFormat("<capsule object %s%s%s at %p>",
279        quote, name, quote, capsule);
280}
281
282
283
284PyDoc_STRVAR(PyCapsule_Type__doc__,
285"Capsule objects let you wrap a C \"void *\" pointer in a Python\n\
286object.  They're a way of passing data through the Python interpreter\n\
287without creating your own custom type.\n\
288\n\
289Capsules are used for communication between extension modules.\n\
290They provide a way for an extension module to export a C interface\n\
291to other extension modules, so that extension modules can use the\n\
292Python import mechanism to link to one another.\n\
293");
294
295PyTypeObject PyCapsule_Type = {
296    PyVarObject_HEAD_INIT(&PyType_Type, 0)
297    "PyCapsule",                /*tp_name*/
298    sizeof(PyCapsule),          /*tp_basicsize*/
299    0,                          /*tp_itemsize*/
300    /* methods */
301    capsule_dealloc, /*tp_dealloc*/
302    0,                          /*tp_vectorcall_offset*/
303    0,                          /*tp_getattr*/
304    0,                          /*tp_setattr*/
305    0,                          /*tp_as_async*/
306    capsule_repr, /*tp_repr*/
307    0,                          /*tp_as_number*/
308    0,                          /*tp_as_sequence*/
309    0,                          /*tp_as_mapping*/
310    0,                          /*tp_hash*/
311    0,                          /*tp_call*/
312    0,                          /*tp_str*/
313    0,                          /*tp_getattro*/
314    0,                          /*tp_setattro*/
315    0,                          /*tp_as_buffer*/
316    0,                          /*tp_flags*/
317    PyCapsule_Type__doc__       /*tp_doc*/
318};
319
320
321