[Pyrex] Is this example correct?
Edward C. Jones
edcjones at erols.com
Tue May 6 00:18:15 CEST 2003
Is the code below correct? Can I reduce the number of calls to malloc?
Any ideas for improvement?
-------------------------
example.h:
typedef union _Num{
int i;
float x;
} Num;
typedef struct _Small {
double x;
double y;
} Small;
typedef struct _AAA {
int k;
Num* nump;
Num num;
Small small;
} AAA;
-------------------------
example.c:
#include "example.h"
-------------------------
tools.pyx:
ctypedef int size_t
cdef extern from "stdlib.h":
void* malloc(size_t size)
void free(void* ptr)
cdef extern from "Python.h":
int PyCObject_Check(object p)
object PyCObject_FromVoidPtr(void* cobj, void (*destr)(void *))
object PyCObject_FromVoidPtrAndDesc(void* cobj, void* desc,
void (*destr)(void *, void *))
void* PyCObject_AsVoidPtr(object self)
void* PyCObject_GetDesc(object self)
cdef class OpaquePtr:
cdef void* p
def __new__(self):
self.p = NULL
def __repr__(self):
if self.p == NULL:
return '<OpaquePtr NULL>'
else:
# Ugly. Cast a pointer to an int. Not portable.
i = <int> self.p
return '<OpaquePtr %x>' % i
cdef wrap_ptr(void* p):
cdef OpaquePtr P
P = OpaquePtr()
P.p = p
return P
cdef void* extract_ptr(OpaquePtr P):
return P.p
-------------------------
wrapped.pyx:
include "tools.pyx"
cdef extern from "example.h":
cdef union _Num:
int i
float x
ctypedef _Num Num
cdef struct _Small:
double x
double y
ctypedef _Small Small
cdef struct _AAA:
int k
Num * nump
Num num
Small small
ctypedef _AAA AAA
#==============================================================
cdef class TemP__Num:
cdef Num* t
def __new__(self, i=0, x=0.0):
self.t = <Num*> malloc(sizeof(Num))
print '<malloc called for Num>'
if self.t == NULL:
raise MemoryError
if i != 0 and x != 0.0:
raise TypeError, 'both i and x are non-zero'
if x != 0.0:
self.t.x = x
else:
self.t.i = i
def __dealloc__(self):
free(self.t)
def __getattr__(self, name):
if name == 'i':
return self.t.i
if name == 'x':
return self.t.x
return object.__getattribute__(self, name)
def __setattr__(self, name, val):
if name == 'i':
self.t.i = val
elif name == 'x':
self.t.x = val
else:
object.__setattr__(self, name, val)
def ToPointer(self):
return PyCObject_FromVoidPtrAndDesc(self.t, 'type Num*', NULL)
#==================================================================
cdef class TemP__Small:
cdef Small* t
def __new__(self, x, y):
self.t = <Small*> malloc(sizeof(Small))
print '<malloc called for Small>'
sys.stdout.flush()
if self.t == NULL:
raise MemoryError
self.t.x = x
self.t.y = y
def __dealloc__(self):
free(self.t)
def __getattr__(self, name):
if name == 'x':
return self.t.x
if name == 'y':
return self.t.y
return object.__getattribute__(self, name)
def __setattr__(self, name, val):
if name == 'x':
self.t.x = val
elif name == 'y':
self.t.y = val
else:
object.__setattr__(self, name, val)
def ToPointer(self):
return PyCObject_FromVoidPtrAndDesc(self.t, 'type Small*', NULL)
#==================================================================
cdef class TemP__AAA:
cdef AAA* t
def __new__(self, k, num, small):
self.t = <AAA*> malloc(sizeof(AAA))
print '<malloc called for AAA>'
if self.t == NULL:
raise MemoryError
self.t.k = k
self.t.nump = NULL
self.t.num.i = num.i
self.t.small.x = small.x
self.t.small.y = small.y
def __dealloc__(self):
free(self.t)
def __getattr__(self, name):
if name == 'k':
return self.t.k
if name == 'nump':
return wrap_ptr(self.t.nump)
if name == 'num':
return TemP__Num(self.t.num.i)
if name == 'small':
return TemP__Small(self.t.small.x, self.t.small.y)
return object.__getattribute__(self, name)
def __setattr__(self, name, val):
if name == 'k':
self.t.k = val
if name == 'nump':
self.t.nump = <Num *> extract_ptr(val)
elif name == 'num':
self.t.num.i = val.i
elif name == 'small':
self.t.small.x = val.x
self.t.small.y = val.y
else:
object.__setattr__(self, name, val)
def ToPointer(self):
return PyCObject_FromVoidPtrAndDesc(self.t, 'type AAA*', NULL)
-------------------------
outer.py:
from wrapped import *
Num = TemP__Num
del TemP__Num
AAA = TemP__AAA
del TemP__AAA
-------------------------
test.py:
#! /usr/bin/env python
import outer
num = outer.Num(0, 1.3)
print 'num.i:', num.i, 'num.x:', num.x
small = outer.Small(3.14159, 2.718)
aaa = outer.AAA(11, num, small)
print 'aaa.k', aaa.k
print 'aaa.num.i', aaa.num.i
print 'aaa.num.x', aaa.num.x
print 'aaa.small.x', aaa.small.x
print 'aaa.small.y', aaa.small.y
numi = outer.Num(33, 0.0)
aaa.num = numi
small2 = outer.Small(37.37, 48.48)
aaa.small = small2
print 'aaa.k', aaa.k
print 'aaa.num.i', aaa.num.i
print 'aaa.num.x', aaa.num.x
print 'aaa.small.x', aaa.small.x
print 'aaa.small.y', aaa.small.y
-------------------------
makeit:
if pyrexc wrapped.pyx
then {
if gcc -c -fPIC -I/usr/include/python2.2/ wrapped.c
then {
gcc -c -fPIC example.c;
gcc -shared example.o wrapped.o -o wrapped.so;
} fi;
} fi;
-------------------------
Output when test.py is run:
<malloc called for Num>
num.i: 1067869798 num.x: 1.29999995232
<malloc called for Small>
<malloc called for AAA>
aaa.k 11
aaa.num.i <malloc called for Num>
1067869798
aaa.num.x <malloc called for Num>
1.29999995232
aaa.small.x <malloc called for Small>
3.14159
aaa.small.y <malloc called for Small>
2.718
<malloc called for Num>
<malloc called for Small>
aaa.k 11
aaa.num.i <malloc called for Num>
33
aaa.num.x <malloc called for Num>
4.62428493227e-44
aaa.small.x <malloc called for Small>
37.37
aaa.small.y <malloc called for Small>
48.48
More information about the Pyrex
mailing list