| 
									
										
										
										
											2009-05-05 22:31:58 +00:00
										 |  |  | /* 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. */ | 
					
						
							| 
									
										
										
										
											2009-06-28 16:23:55 +00:00
										 |  |  |         return name1 == name2; | 
					
						
							| 
									
										
										
										
											2009-05-05 22:31:58 +00:00
										 |  |  |     } | 
					
						
							|  |  |  |     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; | 
					
						
							| 
									
										
										
										
											2009-10-03 20:13:37 +00:00
										 |  |  |     size_t name_length = (strlen(name) + 1) * sizeof(char); | 
					
						
							| 
									
										
										
										
											2009-05-05 22:31:58 +00:00
										 |  |  |     char *name_dup = (char *)PyMem_MALLOC(name_length); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!name_dup) { | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     memcpy(name_dup, name, name_length); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     trace = name_dup; | 
					
						
							|  |  |  |     while (trace) { | 
					
						
							|  |  |  |         char *dot = strchr(trace, '.'); | 
					
						
							|  |  |  |         if (dot) { | 
					
						
							|  |  |  |             *dot++ = '\0'; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (object == NULL) { | 
					
						
							|  |  |  |             if (no_block) { | 
					
						
							|  |  |  |                 object = PyImport_ImportModuleNoBlock(trace); | 
					
						
							|  |  |  |             } else { | 
					
						
							|  |  |  |                 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_DECREF(object); | 
					
						
							|  |  |  |             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_DEL(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) | 
					
						
							| 
									
										
										
										
											2010-08-11 17:31:17 +00:00
										 |  |  |     "PyCapsule",                /*tp_name*/ | 
					
						
							|  |  |  |     sizeof(PyCapsule),          /*tp_basicsize*/ | 
					
						
							|  |  |  |     0,                          /*tp_itemsize*/ | 
					
						
							| 
									
										
										
										
											2009-05-05 22:31:58 +00:00
										 |  |  |     /* methods */ | 
					
						
							|  |  |  |     capsule_dealloc, /*tp_dealloc*/ | 
					
						
							| 
									
										
										
										
											2010-08-11 17:31:17 +00:00
										 |  |  |     0,                          /*tp_print*/ | 
					
						
							|  |  |  |     0,                          /*tp_getattr*/ | 
					
						
							|  |  |  |     0,                          /*tp_setattr*/ | 
					
						
							|  |  |  |     0,                          /*tp_reserved*/ | 
					
						
							| 
									
										
										
										
											2009-05-05 22:31:58 +00:00
										 |  |  |     capsule_repr, /*tp_repr*/ | 
					
						
							| 
									
										
										
										
											2010-08-11 17:31:17 +00:00
										 |  |  |     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*/ | 
					
						
							| 
									
										
										
										
											2009-05-05 22:31:58 +00:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 |