• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
_is_legal_capsule(PyCapsule * capsule,const char * invalid_capsule)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
name_matches(const char * name1,const char * name2)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 *
PyCapsule_New(void * pointer,const char * name,PyCapsule_Destructor destructor)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
PyCapsule_IsValid(PyObject * o,const char * name)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 *
PyCapsule_GetPointer(PyObject * o,const char * name)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 *
PyCapsule_GetName(PyObject * o)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
PyCapsule_GetDestructor(PyObject * o)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 *
PyCapsule_GetContext(PyObject * o)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
PyCapsule_SetPointer(PyObject * o,void * pointer)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
PyCapsule_SetName(PyObject * o,const char * name)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
PyCapsule_SetDestructor(PyObject * o,PyCapsule_Destructor destructor)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
PyCapsule_SetContext(PyObject * o,void * context)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 *
PyCapsule_Import(const char * name,int no_block)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 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             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
capsule_dealloc(PyObject * o)257 capsule_dealloc(PyObject *o)
258 {
259     PyCapsule *capsule = (PyCapsule *)o;
260     if (capsule->destructor) {
261         capsule->destructor(o);
262     }
263     PyObject_Free(o);
264 }
265 
266 
267 static PyObject *
capsule_repr(PyObject * o)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 PyUnicode_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_vectorcall_offset*/
307     0,                          /*tp_getattr*/
308     0,                          /*tp_setattr*/
309     0,                          /*tp_as_async*/
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 };
323 
324 
325