| Benjamin Peterson | b173f78 | 2009-05-05 22:31:58 +0000 | [diff] [blame] | 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. */ | 
| Benjamin Peterson | 3e79190 | 2009-06-28 16:23:55 +0000 | [diff] [blame] | 36 |         return name1 == name2; | 
| Benjamin Peterson | b173f78 | 2009-05-05 22:31:58 +0000 | [diff] [blame] | 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; | 
| Mark Dickinson | 8504d08 | 2009-10-03 20:13:37 +0000 | [diff] [blame] | 200 |     size_t name_length = (strlen(name) + 1) * sizeof(char); | 
| Benjamin Peterson | b173f78 | 2009-05-05 22:31:58 +0000 | [diff] [blame] | 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 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) | 
| Alexander Belopolsky | f0f4514 | 2010-08-11 17:31:17 +0000 | [diff] [blame] | 301 |     "PyCapsule",                /*tp_name*/ | 
 | 302 |     sizeof(PyCapsule),          /*tp_basicsize*/ | 
 | 303 |     0,                          /*tp_itemsize*/ | 
| Benjamin Peterson | b173f78 | 2009-05-05 22:31:58 +0000 | [diff] [blame] | 304 |     /* methods */ | 
 | 305 |     capsule_dealloc, /*tp_dealloc*/ | 
| Alexander Belopolsky | f0f4514 | 2010-08-11 17:31:17 +0000 | [diff] [blame] | 306 |     0,                          /*tp_print*/ | 
 | 307 |     0,                          /*tp_getattr*/ | 
 | 308 |     0,                          /*tp_setattr*/ | 
 | 309 |     0,                          /*tp_reserved*/ | 
| Benjamin Peterson | b173f78 | 2009-05-05 22:31:58 +0000 | [diff] [blame] | 310 |     capsule_repr, /*tp_repr*/ | 
| Alexander Belopolsky | f0f4514 | 2010-08-11 17:31:17 +0000 | [diff] [blame] | 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*/ | 
| Benjamin Peterson | b173f78 | 2009-05-05 22:31:58 +0000 | [diff] [blame] | 322 | }; | 
 | 323 |  | 
 | 324 |  |