[Pyrex] Pybsddb question
tarkawebfoot at charter.net
tarkawebfoot at charter.net
Wed Apr 12 22:44:02 CEST 2006
Hi all,
Been using Pyrex for a few weeks now and am pretty impressed. It provides a great blend of low level access and Python's ease of use.
I'm currently trying to use Pyrex to interface to pybsddb. I need to replace the B-Tree compare function for the dbs I create, so I asked on the pybsddb mailing list how to do that. The following was the response:
>Something like this (untested but it should give you the idea)
>
>class MyBtCompare:
> def __init__(self, reverse=False):
> self.reverse=reverse
> def __call__(self, a, b):
> if self.reverse:
> return cmp(b, a)
> else
> return cmp(a, b)
>
>normaldb = db.DB(...)
>normaldb.set_bt_compare(MyBtCompare())
>backwarddb = db.DB(...)
>backwarddb.set_bt_compare(MyBtCompare(reverse=True))
>
>You should really make that callable comparison "function" class
>faster by dynamically defining the __call__ method in the class at
>__init__ time rather than having it check self.reverse on each
>comparison.
>
>It doesn't have to be a class, just define a function as needed to
>pass to set_bt_compare (better given the above trivial example):
>
>normaldb.set_bt_compare(lambda a, b: cmp(a,b))
>reversedb.set_bt_compare(lambda a, b: cmp(b,a))
Now since this is a time critical function, I'd like the class to be a Pyrex extension class. So I've got the following:
_metadata.pxd:
from _engine cimport c_engine, pcolinfo, oetl_compare, oetl_compare_ab
cdef class c_metadata:
cdef pcolinfo keylist, ordlist, collist
cdef int keylen, ordlen, collen, col_datalen
cdef class row_comparison:
cdef c_metadata meta
cdef int purpose, lstlen, lstdatalen
cdef pcolinfo lst
cdef c_engine parent
cdef char *name
cdef void fire_error(self, int *a, int *b)
_metadata.pyx:
cdef class row_comparison:
def __new__(...):
#build the self.lst object with column info to compare
#also set self.lstlen to number of columns
.
.
.
def __call__(self, DBT *a, DBT *b):
cdef int i, res
res = 0
for i from 0 <= i < self.lstlen:
res = oetl_compare(&self.lst[i], a[0].data, b[0].data)
if res:
if res == ERROR:
self.parent.fire_error(a[0].data, b[0].data)
res = 0
break
return res
Compiling with:
python \python24\scripts\pyrexc -I \python24\lib\site-packages\py_decNumber _metadata.pyx
gives:
C:\Python24\Lib\site-packages\oetl\lib\_metadata.pyx:61:23: Cannot convert Python object argument to type 'DBT (*)'
I guess this isn't suprising since the __call__ function is called by Python. The parameters are going to be passed as Python objects. So the question is, how do I convert them to DBT objects? Just assigning them to cdef DBT objects doesn't work. Do I need to use the Python API to get a pointer to the raw data and typecast it to DBT *?
Thanx for any input
Brian
More information about the Pyrex
mailing list