PyCObject_FromVoidPtr etc.

Martin v. Loewis martin at v.loewis.de
Tue Mar 22 20:15:02 EDT 2011


> Is there a way to keep things (almost) as simple as this using the
> 'Capsules' ?? 

Most certainly. Instead of PyCObject_FromVoidPtr, use PyCapsule_New.
Either pass NULL as a name, or the class name for additional
type-safety. Instead of PyCObject_AsVoidPtr, use PyCapsule_GetPointer.
The only difference will be a change to the destructor function:
it gets the capsule now, rather than the embedded pointer.

> I do understand the advantage of having such a mechanism,
> but in this case it's sort of overkill...

It's the very same mechanism. The only difference is that capsules
are type-safe where CObjects were not. I.e. you can crash the
interpreter by passing in a bad CObject (one for a different type);
with capsules, this can be detected and a Python exception be raised.

Because of the additional type-safety, additional parameters are
needed, and because of that, a new name is needed. Nothing else
has changed.

In fact, you can do:

#if Python-version >= 3.2 (proper test left to the reader)
#define  PyCObject_FromVoidPtr(C, ignored_destroy)
   PyCapsule_New(C, "mymod.Class_XX", destroy_32)
#define PyCObject_AsVoidPtr(P) PyCapsule_GetPointer(P, "mymod.Class_XX")
extern "C" void destroy_32(PyObject *P){
  destroy(PyCapsule_GetPointer(P, "mymod.Class_XX"));
}
#endif

This wouldn't do proper type-checking yet - all callers
of PyCObject_AsVoidPtr then should add

   if (C == NULL) return NULL;

which still should be backwards-compatible with 3.1 and earlier
(in which versions you actually also should check for NULL, since
 even PyCObject_AsVoidPointer can fail, esp. if you are passing
 something that isn't a PyCObject).

Regards,
Martin



More information about the Python-list mailing list