1 
2 /* Wrap void* pointers to be passed between C modules */
3 
4 #include "Python.h"
5 
6 
7 /* Declarations for objects of type PyCObject */
8 
9 typedef void (*destructor1)(void *);
10 typedef void (*destructor2)(void *, void*);
11 
cobject_deprecation_warning(void)12 static int cobject_deprecation_warning(void)
13 {
14     return PyErr_WarnPy3k("CObject type is not supported in 3.x. "
15         "Please use capsule objects instead.", 1);
16 }
17 
18 
19 PyObject *
PyCObject_FromVoidPtr(void * cobj,void (* destr)(void *))20 PyCObject_FromVoidPtr(void *cobj, void (*destr)(void *))
21 {
22     PyCObject *self;
23 
24     if (cobject_deprecation_warning()) {
25         return NULL;
26     }
27 
28     self = PyObject_NEW(PyCObject, &PyCObject_Type);
29     if (self == NULL)
30         return NULL;
31     self->cobject=cobj;
32     self->destructor=destr;
33     self->desc=NULL;
34 
35     return (PyObject *)self;
36 }
37 
38 PyObject *
PyCObject_FromVoidPtrAndDesc(void * cobj,void * desc,void (* destr)(void *,void *))39 PyCObject_FromVoidPtrAndDesc(void *cobj, void *desc,
40                              void (*destr)(void *, void *))
41 {
42     PyCObject *self;
43 
44     if (cobject_deprecation_warning()) {
45         return NULL;
46     }
47 
48     if (!desc) {
49         PyErr_SetString(PyExc_TypeError,
50                         "PyCObject_FromVoidPtrAndDesc called with null"
51                         " description");
52         return NULL;
53     }
54     self = PyObject_NEW(PyCObject, &PyCObject_Type);
55     if (self == NULL)
56         return NULL;
57     self->cobject = cobj;
58     self->destructor = (destructor1)destr;
59     self->desc = desc;
60 
61     return (PyObject *)self;
62 }
63 
64 void *
PyCObject_AsVoidPtr(PyObject * self)65 PyCObject_AsVoidPtr(PyObject *self)
66 {
67     if (self) {
68         if (PyCapsule_CheckExact(self)) {
69             const char *name = PyCapsule_GetName(self);
70             return (void *)PyCapsule_GetPointer(self, name);
71         }
72         if (self->ob_type == &PyCObject_Type)
73             return ((PyCObject *)self)->cobject;
74         PyErr_SetString(PyExc_TypeError,
75                         "PyCObject_AsVoidPtr with non-C-object");
76     }
77     if (!PyErr_Occurred())
78         PyErr_SetString(PyExc_TypeError,
79                         "PyCObject_AsVoidPtr called with null pointer");
80     return NULL;
81 }
82 
83 void *
PyCObject_GetDesc(PyObject * self)84 PyCObject_GetDesc(PyObject *self)
85 {
86     if (self) {
87         if (self->ob_type == &PyCObject_Type)
88             return ((PyCObject *)self)->desc;
89         PyErr_SetString(PyExc_TypeError,
90                         "PyCObject_GetDesc with non-C-object");
91     }
92     if (!PyErr_Occurred())
93         PyErr_SetString(PyExc_TypeError,
94                         "PyCObject_GetDesc called with null pointer");
95     return NULL;
96 }
97 
98 void *
PyCObject_Import(char * module_name,char * name)99 PyCObject_Import(char *module_name, char *name)
100 {
101     PyObject *m, *c;
102     void *r = NULL;
103 
104     if ((m = PyImport_ImportModule(module_name))) {
105         if ((c = PyObject_GetAttrString(m,name))) {
106             r = PyCObject_AsVoidPtr(c);
107             Py_DECREF(c);
108 	}
109         Py_DECREF(m);
110     }
111     return r;
112 }
113 
114 int
PyCObject_SetVoidPtr(PyObject * self,void * cobj)115 PyCObject_SetVoidPtr(PyObject *self, void *cobj)
116 {
117     PyCObject* cself = (PyCObject*)self;
118     if (cself == NULL || !PyCObject_Check(cself) ||
119 	cself->destructor != NULL) {
120 	PyErr_SetString(PyExc_TypeError,
121 			"Invalid call to PyCObject_SetVoidPtr");
122 	return 0;
123     }
124     cself->cobject = cobj;
125     return 1;
126 }
127 
128 static void
PyCObject_dealloc(PyCObject * self)129 PyCObject_dealloc(PyCObject *self)
130 {
131     if (self->destructor) {
132         if(self->desc)
133             ((destructor2)(self->destructor))(self->cobject, self->desc);
134         else
135             (self->destructor)(self->cobject);
136     }
137     PyObject_DEL(self);
138 }
139 
140 
141 PyDoc_STRVAR(PyCObject_Type__doc__,
142 "C objects to be exported from one extension module to another\n\
143 \n\
144 C objects are used for communication between extension modules.  They\n\
145 provide a way for an extension module to export a C interface to other\n\
146 extension modules, so that extension modules can use the Python import\n\
147 mechanism to link to one another.");
148 
149 PyTypeObject PyCObject_Type = {
150     PyVarObject_HEAD_INIT(&PyType_Type, 0)
151     "PyCObject",		/*tp_name*/
152     sizeof(PyCObject),		/*tp_basicsize*/
153     0,				/*tp_itemsize*/
154     /* methods */
155     (destructor)PyCObject_dealloc, /*tp_dealloc*/
156     0,				/*tp_print*/
157     0,				/*tp_getattr*/
158     0,				/*tp_setattr*/
159     0,				/*tp_compare*/
160     0,				/*tp_repr*/
161     0,				/*tp_as_number*/
162     0,				/*tp_as_sequence*/
163     0,				/*tp_as_mapping*/
164     0,				/*tp_hash*/
165     0,				/*tp_call*/
166     0,				/*tp_str*/
167     0,				/*tp_getattro*/
168     0,				/*tp_setattro*/
169     0,				/*tp_as_buffer*/
170     0,				/*tp_flags*/
171     PyCObject_Type__doc__	/*tp_doc*/
172 };
173