Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

ctypes and garbage collection

1 view
Skip to first unread message

Joakim Hove

unread,
Sep 6, 2010, 8:28:15 AM9/6/10
to
Hello,

I have used ctypes to wrap a C-library - it has been a really painless
experience!

The C-library instantiates a quite large "container-like" structure.
There are then several functions to inspect the content of the
container, get at items and free the whole thing:

/* C - code */
c_container_type * c_container_alloc( const char * filename );
c_node_type * c_container_get_node( c_container_type *
container , const char * node_id );
void c_container_free( c_container_type *
container );
....

Observe that the c_container_get_node() function does _not_ allocate
memory, it just returns a opaque handle to a node structure, still
fully owned by the container structure. I have wrapped this with
Python/ctypes roughly like this (severly trimmed pseudo code):

class Container:
def __init__(self , filename):
self.c_ptr = c_container_alloc( filename )

def __del__( self ):
c_container_free( self.c_ptr )

def get_node( self , node_id):
Node( c_container_get_node( self , node_id ))


class Node:
def __init__( self , c_ptr ):
self.c_ptr = c_ptr

def __del__( self ):
pass


Now, a use scenario might be like this:

1. Instantiate a Container() instance.
2. Instantiate a Node() instance with the Container.get_node()
function.
3. Forget about the Container instance and work happily with the Node
instance.
4. Out of the blue comes the gc - and then? Will the Node instance be
enough to protect the Container instance from beeing garbage
collected?

I thought maybe the get_node() function should have something like a
incref() call, and the Node.__del__() function a corresponding
decref()? Or ??


Regards

Joakim Hove

Ulrich Eckhardt

unread,
Sep 6, 2010, 9:11:14 AM9/6/10
to
Joakim Hove wrote:
> I have used ctypes to wrap a C-library
> [...]
> Observe that the c_container_get_node() function does _not_ allocate
> memory, it just returns a opaque handle to a node structure, still
> fully owned by the container structure.
[...]

>
> class Container:
> def __init__(self , filename):
> self.c_ptr = c_container_alloc( filename )
>
> def __del__( self ):
> c_container_free( self.c_ptr )
>
> def get_node( self , node_id):
> Node( c_container_get_node( self , node_id ))
>
>
> class Node:
> def __init__( self , c_ptr ):
> self.c_ptr = c_ptr
>
> def __del__( self ):
> pass
>
>
> Now, a use scenario might be like this:
>
> 1. Instantiate a Container() instance.
> 2. Instantiate a Node() instance with the Container.get_node()
> function.
> 3. Forget about the Container instance and work happily with the Node
> instance.
> 4. Out of the blue comes the gc - and then? Will the Node instance be
> enough to protect the Container instance from beeing garbage
> collected?

No. You should be able to even see that by logging calls to alloc/free of
your library.

> I thought maybe the get_node() function should have something like a
> incref() call, and the Node.__del__() function a corresponding
> decref()? Or ??

I'd add an "__owner" field to the node, initialised with the owning
container instance.

Uli

--
Sator Laser GmbH
Geschäftsführer: Thorsten Föcking, Amtsgericht Hamburg HR B62 932

Joakim Hove

unread,
Sep 6, 2010, 9:22:22 AM9/6/10
to
> I'd add an "__owner" field to the node, initialised with the owning
> container instance.

I will - thank you!

Joakim

0 new messages