[Pyrex] C++, references, deref a pointer...

Lenard Lindstrom len-l at telus.net
Sat Apr 8 05:05:19 CEST 2006


On 7 Apr 2006 at 11:52, John Sutherland wrote:

> Hi all... I've been working with Lenard's C++ patches, and found one  
> problem, and have some other questions..
> 
> The problem I found is when trying his example to wrap C++ methods  
> from a previous post (in repsonse to someone else's C++ wrapper).. I  
> wasn't able to get it to recongize  the C++ methods of a class.. i  
> would get errors say that it the class stucture didn't have that  
> attirbute.. So I had to modify Compler/ExprNodes.py to handle it:
> 
> Approx line 1576 was:
> if entry.is_variable or entry.is_cmethod:
> to
> if entry.is_variable or entry.is_cmethod or entry.is_cfunction:
> 
I do not understand this change. An extension class attribute cannot 
be a C function. It can be a C function pointer, which is just a C 
attribute. See below.

> then I was able to compile, and it seems to work..
> 
> Now for my questions...
> I have a couple classes I'm wrapping where one of them takes a  
> reference to the other, and I can't seem to figure out the magic to  
> get it to work...
> 
> Example (not from actaul code. forgive mistakes):
> 
> class Record {
> 	Record()
> 	~Record()
> }
> 
> class Set {
> 	Set()
> 	~Set()
> 	addRecord( Record& )
> }
> 
> Python:
> cdef extern from "../rrec.h":
> 	ctypedef struct record "Record":
> 		<sturct full of functions>
> 	record *myRecordFactory "new Record" ()
> 
> cdef extern from "../rrset.h":
>      ctypedef struct rrset "RRSet":
>          int addRecord "addRecord" ( record )
>      rrset *myRRSetFactory "new RRSet" ()
> 
            int (*addRecord) "addRecord" (record)

Treat C++ methods as function pointers.

> cdef class Record:
>      cdef rrec *thisptr
> 
>      def __init__(self):
>          self.thisptr = myRecordFactory()
> 
> 
> cdef class RRSet:
> 	cdef rrset *thisptr
>      def __init__(self):
>          self.thisptr = myRRSetFactory()
> 
>      def addRR( self, RRec rr not None):
>          self.thisptr.addRR( <rrec>rr.thisptr )
> 	
> I can't seem to figure out the mojo to get the cast right... I can't  
> seem to deref the pointer, or be able to get a reference...
> 
> 
> Any ideas?
> 	
cdef class RRSet:
    ...
    def addRR(self, Record rr not None):
        self.thisptr.addRecord(rr.thisptr[0])

Declaring rr as Record allows access to its C field thisptr; no 
recasting is necessary.  addRecord expects a C++ reference so pointer 
rr.thisptr has to be dereferenced.

The following example is tested with GCC and Python 2.4 on Windows:

---  Klass.h ---
class Record
{
 public:
  Record(int i);
  ~Record();
  int i;
};

Record::Record(int i)
{
  this->i = i;
}

Record::~Record()
{
  this->i = 0;
}

class Set
{
 public:
  int AddRecord(Record &r);
};

int Set::AddRecord(Record &r)
{
  return r.i;
}

--- record.pyx ---
cdef extern from "Klass.h":
    struct record "Record":
        pass
    struct record_set "Set":
        int (* AddRecord)(record r)
    record *RecordFactory "new Record" (int i)
    record_set *SetFactory "new Set" ()
    void delete "delete " (void *o)

cdef class Record:
    cdef record *thisptr
    def __new__(self, int i):
        self.thisptr = RecordFactory(i)
    def __dealloc__(self):
        delete(self.thisptr)

cdef class Set:
    cdef record_set *thisptr
    def __new__(self):
        self.thisptr = SetFactory()
    def __dealloc__(self):
        delete(self.thisptr)
    def AddRecord(self, Record r not None):
        print self.thisptr.AddRecord(r.thisptr[0])

Lenard Lindstrom
<len-l at telus.net>




More information about the Pyrex mailing list