
Also, the method seems rather complicated for doing a simple thing. The only thing I really want is a way to refer to an _New or _Convert method from Python code.
I believe the attached code implements your requirements. In particular, see PyArg_GenericCopy for an application that extracts a void* from an object through a type-safe protocol, then creates a clone of the original object through the same protocol. Both extractor and creator function are associated with the type object. To see this work in Python, run
import handle x=handle.new(10) x <handle.Handle object at 0x81683a0> y=handle.copy(x) y <handle.Handle object at 0x819f270>
Regards, Martin #include "Python.h" /************* Generic Converters ***************/ struct converters{ PyObject* (*create)(void*); int (*extract)(PyObject*, void**); }; char descr_string[] = "calldll converter structure"; void PyArg_AddConverters(PyTypeObject *type, struct converters* convs) { PyObject *cobj = PyCObject_FromVoidPtrAndDesc(convs, descr_string, NULL); PyDict_SetItemString(type->tp_dict, "__calldll__", cobj); Py_DECREF(cobj); } struct converters* PyArg_GetConverters(PyTypeObject *type) { PyObject *cobj; void *descr; cobj = PyObject_GetAttrString((PyObject*)type, "__calldll__"); if (!cobj) return NULL; descr = PyCObject_GetDesc(cobj); if (!descr) return NULL; if (descr != descr_string){ PyErr_SetString(PyExc_TypeError, "invalid cobj"); return NULL; } return (struct converters*)PyCObject_AsVoidPtr(cobj); } PyObject *PyArg_Create(PyTypeObject* type, void * value) { struct converters *convs = PyArg_GetConverters(type); if (!convs) return NULL; return convs->create(value); } int PyArg_Extract(PyObject* obj, void** value) { struct converters *convs = PyArg_GetConverters(obj->ob_type); if (!convs) return -1; convs->extract(obj, value); return 0; } PyObject* PyArg_GenericCopy(PyObject* obj) { void *tmp; if (PyArg_Extract(obj, &tmp)) return NULL; return PyArg_Create(obj->ob_type, tmp); } /************* End Generic Converters ***************/ typedef struct { PyObject_HEAD int handle; } HandleObject; staticforward PyTypeObject Handle_Type; #define HandleObject_Check(v) ((v)->ob_type == &Handle_Type) static HandleObject * newHandleObject(int i) { HandleObject *self; self = PyObject_New(HandleObject, &Handle_Type); if (self == NULL) return NULL; self->handle = i; return self; } /* Handle methods */ static void Handle_dealloc(HandleObject *self) { PyObject_Del(self); } /**************** Generic Converters: Handle support ***************/ static PyObject* handle_conv_new(void *s){ return (PyObject*)newHandleObject((int)s); } static int handle_conv_extract(PyObject *o, void **dest){ HandleObject *h = (HandleObject*)o; *dest = (void*)h->handle; return 0; } struct converters HandleConvs = { handle_conv_new, handle_conv_extract }; /**************** Generic Converters: Handle support ***************/ statichere PyTypeObject Handle_Type = { /* The ob_type field must be initialized in the module init function * to be portable to Windows without using C++. */ PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "handle.Handle", /*tp_name*/ sizeof(HandleObject), /*tp_basicsize*/ 0, /*tp_itemsize*/ /* methods */ (destructor)Handle_dealloc, /*tp_dealloc*/ 0, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ 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*/ Py_TPFLAGS_DEFAULT, /*tp_flags*/ }; /* --------------------------------------------------------------------- */ static PyObject * xx_new(PyObject *self, PyObject *args) { HandleObject *rv; int h; if (!PyArg_ParseTuple(args, "i:new", &h)) return NULL; rv = newHandleObject(h); if ( rv == NULL ) return NULL; return (PyObject *)rv; } static PyObject * xx_copy(PyObject *self, PyObject *args) { PyObject *obj; if (!PyArg_ParseTuple(args, "O:copy", &obj)) return NULL; return PyArg_GenericCopy(obj); } static PyMethodDef xx_methods[] = { {"new", xx_new, METH_VARARGS}, {"copy", xx_copy, METH_VARARGS}, {NULL, NULL} /* sentinel */ }; DL_EXPORT(void) inithandle(void) { PyObject *m; Handle_Type.ob_type = &PyType_Type; PyType_Ready(&Handle_Type); PyArg_AddConverters(&Handle_Type, &HandleConvs); /* Create the module and add the functions */ m = Py_InitModule("handle", xx_methods); }