[PyKDE] question about sip wrapping of PyObject
Tony Willis
Tony.Willis at nrc-cnrc.gc.ca
Wed Nov 3 03:14:50 GMT 2004
Hi
I am trying to extend Paul Kunz' HippoDraw package so that it can work
efficiently inside a larger python script that makes extensive use of
PyQt and thus of the sip environment. At present in order to store
data internally inside the sip-wrapped version of HippoDraw I have to
go from numarray object -> python list -> HippoDraw NTuple. This
has a real impact on performance. Basically I want to avoid any data
conversion whatsoever but use the numarray objects themselves.
my environment - RH 9 linux, sip 4.0.1, python 2.3.4, numarray 0.9,
gcc 3.2.2.
On the C++ side of things I have managed to create a class which
will, I hope, do what I want. Basically its just a std::vector of
PyArrayObject pointers.
In Python I want to be able to say e.g.:
self._radius_ntuple = SipArrayTuple();
self._radius_ntuple.addColumn("demo",x_pos)
where x_pos is a 1-dimensional python 'numarray' object.
Here are extractions from the SipArrayTuple.h and SipArrayTuple.cc
code that I hope will implement this stuff on the C++ side of things.
The full versions of this code compile OK.
/////////// SipArrayTuple.h //////////////
#ifndef SipArrayTuple_H
#define SipArrayTuple_H
#include <Python.h>
#include <numarray/libnumarray.h>
#include "datasrcs/DataSource.h"
class MDL_HIPPOPLOT_API SipArrayTuple : public DataSource
{
private:
std::vector < PyArrayObject* > m_data;
public:
SipArrayTuple ();
/** Adds a column to the end of the SipArrayTuple. If the size of the
input array is the same as the size of the existing columns adds
input array to then end of the SipArrayTuple . Gives the column the
label @a label. Returns the index of the newly created column.
If the size of the input array differs from the size of existing
columns or if the label already exists, then throws a
DataSourceException object.
*/
int addColumn ( const std::string & label,
PyObject * array );
};
#endif // SipArrayTuple_H
/////////////// end SipArrayTuple.h ////////////////////
/////////// SipArrayTuple.cc ////////////////
#include "SipArrayTuple.h"
#include <algorithm>
#include <numeric>
using std::string;
using std::vector;
SipArrayTuple::SipArrayTuple ()
: DataSource ()
{
}
int SipArrayTuple:: addColumn ( const std::string & label,
PyObject * array )
{
m_data.push_back ((PyArrayObject *) array );
addLabel ( label );
return m_data.size() - 1;
}
/////////////// end SipArrayTuple.cc ////////////////////
However I'm having trouble with the 'sip' wrapper code. The larger
sihippo.sip that includes SipArrayTuple.sip is:
/////////////// sihippo.sip ////////////////////
%Module sihippo
%Import qt/qtmod.sip
%Import qtcanvasmod.sip
// lots of other files
%Include vector.sip
%Include SipArrayTuple.sip
/////////////// end sihippo.sip //////////////
When I run this through sip (4.0.1) this is what I get:
[tonywlp 4:12pm] [sip]> make
creating built sources
sip -e -g -c . -I /usr/local/share/sip -I /usr/local/share/sip/qtcanvas -I ../numarray -I ../sip \
-t Qt_3_2_0 -t WS_X11 ../sip/sihippo.sip
sip: PyObject is undefined
make: *** [sipsihippocmodule.h] Error 1
Here is the extraction from SipArrayTuple.sip that wraps the addColumn
call:
/////////////// SipArrayTuple.sip ////////////////////
%PostInitialisationCode
import_libnumarray();
%End
class SipArrayTuple : DataSource
{
%TypeHeaderCode
#include "numarray/SipArrayTuple.h"
#include <string>
%End
public:
int addColumn ( const std::string &, PyObject *)
throw ( DataSourceException );
};
/////////////// end SipArrayTuple.sip ////////////////////
Basically I'm confused about how to tell SipArrayTuple.sip to pick up
the definition for PyObject. If I comment out the inclusion
of SipArrayTuple.sip in sihippo.sip above, the vector.sip code
passes through sip OK. Is it because inside vector.sip (see below)
the PyObject pointer is used inside a %ConvertFromTypeCode block?
I don't think I need to do any Convert stuff.
Also is there some particular place I should put the
%PostInitialisationCode
import_libnumarray();
%End
in sihippo.sip?, or can I leave it where it is?
I would appreciate any and all advice - I'm pretty much a python / sip
newbie! Could you please copy a reply directly to my e-mail
address Tony.Willis at nrc-cnrc.gc.ca as I don't read this list very often.
Thank you!
Tony
___________
Tony Willis
National Research Council Tony.Willis at nrc-cnrc.gc.ca
Box 248 (250)493-2277
Penticton, BC V2A 6J9 fax: 493-7767
Government of Canada Gouvernement du Canada
/////////////// extraction from vector.sip ////////////////////
%MappedType std::vector<double>
{
%TypeHeaderCode
#include <vector>
%End
%ConvertFromTypeCode
// Handle no list.
if (!sipCpp)
return PyList_New(0);
// Convert to a Python list of doubles
PyObject *l;
// Create the list.
if ((l = PyList_New(sipCpp -> size())) == NULL)
return NULL;
// Get it.
for ( unsigned int i = 0; i < sipCpp -> size(); ++i)
if (PyList_SetItem(l,i,PyFloat_FromDouble((double)(*sipCpp)[i])) < 0)
{
Py_DECREF(l);
return NULL;
}
return l;
%End
}
/////////////// end extraction from vector.sip ////////////////////
More information about the PyQt
mailing list