No issues found
1 /* Wrap void * pointers to be passed between C modules */
2
3 #include "Python.h"
4
5 /* Internal structure of PyCapsule */
6 typedef struct {
7 PyObject_HEAD
8 void *pointer;
9 const char *name;
10 void *context;
11 PyCapsule_Destructor destructor;
12 } PyCapsule;
13
14
15
16 static 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
31 static int
32 name_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
43 PyObject *
44 PyCapsule_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
67 int
68 PyCapsule_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
79 void *
80 PyCapsule_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
97 const char *
98 PyCapsule_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
109 PyCapsule_Destructor
110 PyCapsule_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
121 void *
122 PyCapsule_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
133 int
134 PyCapsule_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
152 int
153 PyCapsule_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
166 int
167 PyCapsule_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
180 int
181 PyCapsule_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
194 void *
195 PyCapsule_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 NULL;
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 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
247 EXIT:
248 Py_XDECREF(object);
249 if (name_dup) {
250 PyMem_FREE(name_dup);
251 }
252 return return_value;
253 }
254
255
256 static void
257 capsule_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
267 static PyObject *
268 capsule_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 PyString_FromFormat("<capsule object %s%s%s at %p>",
283 quote, name, quote, capsule);
284 }
285
286
287
288 PyDoc_STRVAR(PyCapsule_Type__doc__,
289 "Capsule objects let you wrap a C \"void *\" pointer in a Python\n\
290 object. They're a way of passing data through the Python interpreter\n\
291 without creating your own custom type.\n\
292 \n\
293 Capsules are used for communication between extension modules.\n\
294 They provide a way for an extension module to export a C interface\n\
295 to other extension modules, so that extension modules can use the\n\
296 Python import mechanism to link to one another.\n\
297 ");
298
299 PyTypeObject PyCapsule_Type = {
300 PyVarObject_HEAD_INIT(&PyType_Type, 0)
301 "PyCapsule", /*tp_name*/
302 sizeof(PyCapsule), /*tp_basicsize*/
303 0, /*tp_itemsize*/
304 /* methods */
305 capsule_dealloc, /*tp_dealloc*/
306 0, /*tp_print*/
307 0, /*tp_getattr*/
308 0, /*tp_setattr*/
309 0, /*tp_reserved*/
310 capsule_repr, /*tp_repr*/
311 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*/
322 };