Retain reference to a struct

Carsten Haese carsten at uniqsys.com
Wed Nov 2 16:55:56 EST 2005


On Wed, 2005-11-02 at 16:23, andychambers2002 at yahoo.co.uk wrote:
> Hi All,
> 
> A C library I'm using has a number of functions that all require a
> struct as an argument.  The example module shows how to make a new
> Python Object from C code and I've seen other posts that recommend this
> way of doing it.
> 
> In this case though, it would seem easier if I could create the object
> in the Python code.  This would require storing a pointer to an
> instance of the struct until a certain function is called.
> 
> I can get the pointer into the python code, but whenever I try to use
> it to call another function, the module segfaults.  Can anyone suggest
> why this is?
> 
> static PyObject *
> libpyq_PQconnectdb(PyObject *self, PyObject *args)
> {
>         PGconn *conn = PyMem_New(PGconn, sizeof(PGconn *));
>         conn = (PGconn *)PQconnectdb((const char*)
> PyString_AS_STRING(args));
> 
>         printf("%p", conn);
>         return PyLong_FromVoidPtr(conn) ;
> }
> 
> static PyObject *
> libpyq_PQfinish(PyObject *self, PyObject *args)
> {
>         printf("%p", args);
>         return 1;

What exactly do you think you're returning here? The function
declaration says that you're supposed to return a pointer to a PyObject.
'1' is not likely to be a valid pointer to anything.

> }
> 
> >>> import libpyq                #works fine
> >>> conn = libpyq.PQconnectdb    #conn now a pointer

Are you sure that's the correct example code? As written, that line
doesn't call the PQconnectdb function. It assigns "conn" to be an
alternate name for the PQconnectdb function.

> >>> libpyq.PQfinish(conn)        #segfaults

That's probably due to the fact that the python interpreter wants to
look up your return value for printing it, but you're returning a bogus
pointer.

> I'm new to C but relatively experienced with Python.  I have a sneaky
> suspiscion there's a good reason for not doing it this way but I
> haven't seen a good explanation of why not yet.  If you know one,
> please tell me.

The idea of passing around pointers as numbers is very unpythonic. There
is no guarantee that the number that's passed into PQfinish actually
came from a call to PQconnectdb. The user could pass in any integer and
(probably successfully) attempt to crash the system. You should really
wrap the C struct (or the pointer to the C struct) into a Python object
instead.

By the way, it looks like you're trying to write some sort of database
access module. The 'pq' looks suspiciously like it's for PostgreSQL. If
that's the case, can't you just use an existing module for connecting to
PostgreSQL?

HTH,

Carsten Haese.





More information about the Python-list mailing list