[Pyrex] wrapping structures that can not be created directly

Yann Vernier yann at donkey.dyndns.org
Sat Dec 11 12:40:31 CET 2004


On Fri, Dec 10, 2004 at 11:15:17PM -0700, Phil Frost wrote:
> I am trying to wrap a C library that has a number of structures that are
> not allocated directly, but obtained by methods on other structures.
> 
> In this case, it's a filesystem library. There is a structure and set of
> associated functions for a directory, but a directory can only be
> obtained by 'getroot' on a filesystem or 'lookup' on an existing
> directory. What I want to do is something like:
> 
> cdef class Directory:
>     cdef dir_t *dir
>     def __new__(self, dir_t *dir):
>         self.dir = dir
> 
> This way, a Directory can never be created without self.dir being a
> valid pointer to dir_t. I'd like to avoid checking that self.dir is not
> NULL in each method if possible.

You must get that dir_t* from somewhere. In this case, you require it to
be available as a Python type, since Directory.__new__ is effectively
called from Python. I had a somewhat similar issue when messing around
with yet another xine-lib wrapper, in which I did something odd like
this (chopped for brevity):

In xine.pxd:

cdef class xine:
  cdef xine_t *xine

cdef class xine_stream:
  cdef xine myxine
  cdef xine_stream_t *stream


In xine.pyx:

cdef class xine:
  def __new__(self, *ignored, **ignoredtoo):
    self.xine=xineh.xine_new()
    if self.xine is NULL:
      raise RuntimeError("Failed to instantiate Xine")
  def stream(self, *passed, **passedtoo):
    return xine_stream(self, *passed, **passedtoo)
  def __dealloc__(self):
    if self.xine is not NULL:
      xineh.xine_exit(self.xine)

cdef class xine_stream:
  def __new__(self, xine myxine not None, audio_port ao not None, video_port vo not None, *ignored, **ignoredtoo):
    self.myxine=myxine
    self.stream=xineh.xine_stream_new(myxine.xine, ao.audio, vo.video)
  def __dealloc__(self):
    if self.stream is not NULL:
      xineh.xine_dispose(self.stream)


This method lets me be sure that the xine_t pointer is still valid,
since I hold a reference to the wrapping xine type. Since that's
available in Python, it's also passable as an argument for Python
methods. The dealloc methods must test for NULL in case new raised an
exception as they still get called. The *_port classes wrap their own
pointers in a similar manner.

As a side note, I probably wanted to hide the xine_stream type from
being visible at the top level of xine.pxd. I guess that's possible by
cimporting it from another pyx before using it in xine.stream.

Is it possible to make a cdef class initializer that can take pure C
arguments, which don't have a corresponding Python type?

-- 
PGP fingerprint = 9242 DC15 2502 FEAB E15F  84C6 D538 EC09 5380 5746
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: Digital signature
Url : http://lists.copyleft.no/pipermail/pyrex/attachments/20041211/adb5686e/attachment.bin


More information about the Pyrex mailing list