| #include "parts.h" | |
| #include <stdlib.h> // free() | |
| static void | |
| capsule_destructor(PyObject *op) | |
| { | |
| /* If non-NULL, the name and the pointer are the same allocation. */ | |
| free((char *)PyCapsule_GetName(op)); | |
| } | |
| static PyObject * | |
| capsule_new(PyObject *self, PyObject *arg) | |
| { | |
| const char *name; | |
| Py_ssize_t size; | |
| if (!PyArg_Parse(arg, "z#", &name, &size)) { | |
| return NULL; | |
| } | |
| char *name_copy = NULL; | |
| if (name != NULL) { | |
| name_copy = strdup(name); | |
| if (name_copy == NULL) { | |
| return PyErr_NoMemory(); | |
| } | |
| } | |
| static const char dummy = 0; | |
| void *pointer = name_copy != NULL ? (void *)name_copy : (void *)&dummy; | |
| PyObject *capsule = PyCapsule_New(pointer, name_copy, capsule_destructor); | |
| if (capsule == NULL) { | |
| free(name_copy); | |
| } | |
| return capsule; | |
| } | |
| static PyObject * | |
| pycapsule_import(PyObject *self, PyObject *args) | |
| { | |
| const char *name; | |
| Py_ssize_t size; | |
| int no_block = 0; | |
| if (!PyArg_ParseTuple(args, "z#|i", &name, &size, &no_block)) { | |
| return NULL; | |
| } | |
| void *pointer = PyCapsule_Import(name, no_block); | |
| if (pointer == NULL) { | |
| return NULL; | |
| } | |
| /* Capsules created by capsule_new() store a copy of their name as the | |
| pointer, so a successful import round-trips the name. Only use this | |
| function with such capsules. */ | |
| return PyUnicode_FromString((const char *)pointer); | |
| } | |
| static PyMethodDef test_methods[] = { | |
| {"capsule_new", capsule_new, METH_O}, | |
| {"PyCapsule_Import", pycapsule_import, METH_VARARGS}, | |
| {NULL}, | |
| }; | |
| int | |
| _PyTestLimitedCAPI_Init_Capsule(PyObject *m) | |
| { | |
| return PyModule_AddFunctions(m, test_methods); | |
| } |