0

In http://docs.cython.org/src/userguide/extension_types.html#external-extension-types it's explained how to access internal (hidden or "private") C-level members of objects in a Python extension module.

I want to access the internal member db from a sqlite3.Connection object which is defined in a struct pysqlite_Connection in file Modules/_sqlite/connection.h of the Python2 source. I do it like this:

File connection.pxd:

cdef extern from "connection.h":
    struct sqlite3Connection:
        sqlite3 *db

    ctypedef class __builtin__.xConnection [object pysqlite_Connection]:
        cdef sqlite3Connection conn

and then use it like this:

File vtables.pxd:

from connection cimport xConnection

cdef dbname(xConnection c):
    cdef sqlite3 *d
    return sqlite3_db_filename(c.conn.db, "main")

This compiles with cython, but when I run the C compiler on the result, I get:

vtables.c:635:69: error: ‘pysqlite_Connection’ has no member named ‘conn’
   __pyx_t_1 = __Pyx_PyBytes_FromString(sqlite3_db_filename(__pyx_v_c->conn.db, __pyx_k_main)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 6; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
                                                                     ^

The generated C code seems to act as if I was accessing the pysqlite_Connection struct instead of the wrapping xConnection, complaining about access to a member conn which is of course not in pysqlite_Connection but in my xConnection Cython class. But in the dbname function the parameter is clearly defined as xConnection. This seems like a bug in the cython compiler. Or did I miss something?

I tried to give the type parameter as in the documentation, like:

ctypedef class __builtin__.xConnection [object pysqlite_Connection, type pysqlite_ConnectionType]:
    cdef sqlite3Connection conn

but then cython crashed.

If this method is obsolete/not supported anymore, are there any alternatives?

1 Answers1

2

I don't think you've quite done what you think you've done. You haven't created a wrapper class called xConnection. You've assured Cython that there is already a class called __builtin__.xConnection and that it is stored using the C structure pysqlite_Connection, and it contains a sqlite3Connection struct which contains a member called db.

I think what you want to tell Cython that there is already a class called sqlite.Connection, that is stored in the C structure pysqlite_Connection and which contains a member called db:

cdef extern from "connection.h":
    # I assume you definite this somewhere else
    ctypedef struct sqlite3:
        pass

    ctypedef class sqlite.Connection [object pysqlite_Connection]:
        cdef sqlite3* db

cdef dbname(Connection c):
    return sqlite3_db_filename(c.db, "main")
DavidW
  • 29,336
  • 6
  • 55
  • 86