blob: ed24cc1d6a2eb2be9c3d8d0142727f48b33ab1b6 [file] [log] [blame]
Benjamin Petersonb173f782009-05-05 22:31:58 +00001/* 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. */
Benjamin Peterson3e791902009-06-28 16:23:55 +000036 return name1 == name2;
Benjamin Petersonb173f782009-05-05 22:31:58 +000037 }
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
Victor Stinner92055202020-04-08 00:38:15 +020053 capsule = PyObject_New(PyCapsule, &PyCapsule_Type);
Benjamin Petersonb173f782009-05-05 22:31:58 +000054 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;
Mark Dickinson8504d082009-10-03 20:13:37 +0000200 size_t name_length = (strlen(name) + 1) * sizeof(char);
Benjamin Petersonb173f782009-05-05 22:31:58 +0000201 char *name_dup = (char *)PyMem_MALLOC(name_length);
202
203 if (!name_dup) {
Zackery Spytz4c49da02018-12-07 03:11:30 -0700204 return PyErr_NoMemory();
Benjamin Petersonb173f782009-05-05 22:31:58 +0000205 }
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 if (no_block) {
218 object = PyImport_ImportModuleNoBlock(trace);
219 } else {
220 object = PyImport_ImportModule(trace);
221 if (!object) {
222 PyErr_Format(PyExc_ImportError, "PyCapsule_Import could not import module \"%s\"", trace);
223 }
224 }
225 } else {
226 PyObject *object2 = PyObject_GetAttrString(object, trace);
227 Py_DECREF(object);
228 object = object2;
229 }
230 if (!object) {
231 goto EXIT;
232 }
233
234 trace = dot;
235 }
236
237 /* compare attribute name to module.name by hand */
238 if (PyCapsule_IsValid(object, name)) {
239 PyCapsule *capsule = (PyCapsule *)object;
240 return_value = capsule->pointer;
241 } else {
242 PyErr_Format(PyExc_AttributeError,
243 "PyCapsule_Import \"%s\" is not valid",
244 name);
245 }
246
247EXIT:
248 Py_XDECREF(object);
249 if (name_dup) {
250 PyMem_FREE(name_dup);
251 }
252 return return_value;
253}
254
255
256static void
257capsule_dealloc(PyObject *o)
258{
259 PyCapsule *capsule = (PyCapsule *)o;
260 if (capsule->destructor) {
261 capsule->destructor(o);
262 }
263 PyObject_DEL(o);
264}
265
266
267static PyObject *
268capsule_repr(PyObject *o)
269{
270 PyCapsule *capsule = (PyCapsule *)o;
271 const char *name;
272 const char *quote;
273
274 if (capsule->name) {
275 quote = "\"";
276 name = capsule->name;
277 } else {
278 quote = "";
279 name = "NULL";
280 }
281
282 return PyUnicode_FromFormat("<capsule object %s%s%s at %p>",
283 quote, name, quote, capsule);
284}
285
286
287
288PyDoc_STRVAR(PyCapsule_Type__doc__,
289"Capsule objects let you wrap a C \"void *\" pointer in a Python\n\
290object. They're a way of passing data through the Python interpreter\n\
291without creating your own custom type.\n\
292\n\
293Capsules are used for communication between extension modules.\n\
294They provide a way for an extension module to export a C interface\n\
295to other extension modules, so that extension modules can use the\n\
296Python import mechanism to link to one another.\n\
297");
298
299PyTypeObject PyCapsule_Type = {
300 PyVarObject_HEAD_INIT(&PyType_Type, 0)
Alexander Belopolskyf0f45142010-08-11 17:31:17 +0000301 "PyCapsule", /*tp_name*/
302 sizeof(PyCapsule), /*tp_basicsize*/
303 0, /*tp_itemsize*/
Benjamin Petersonb173f782009-05-05 22:31:58 +0000304 /* methods */
305 capsule_dealloc, /*tp_dealloc*/
Jeroen Demeyer530f5062019-05-31 04:13:39 +0200306 0, /*tp_vectorcall_offset*/
Alexander Belopolskyf0f45142010-08-11 17:31:17 +0000307 0, /*tp_getattr*/
308 0, /*tp_setattr*/
Jeroen Demeyer530f5062019-05-31 04:13:39 +0200309 0, /*tp_as_async*/
Benjamin Petersonb173f782009-05-05 22:31:58 +0000310 capsule_repr, /*tp_repr*/
Alexander Belopolskyf0f45142010-08-11 17:31:17 +0000311 0, /*tp_as_number*/
312 0, /*tp_as_sequence*/
313 0, /*tp_as_mapping*/
314 0, /*tp_hash*/
315 0, /*tp_call*/
316 0, /*tp_str*/
317 0, /*tp_getattro*/
318 0, /*tp_setattro*/
319 0, /*tp_as_buffer*/
320 0, /*tp_flags*/
321 PyCapsule_Type__doc__ /*tp_doc*/
Benjamin Petersonb173f782009-05-05 22:31:58 +0000322};
323
324