[GRASS-dev] RE: [GRASS-user] Question with Python-SWIG example [SEC=UNCLASSIFIED]

Glynn Clements glynn at gclements.plus.com
Sun May 16 12:50:40 EDT 2010

Glynn Clements wrote:

> I also found ctypesgen:
> 	http://code.google.com/p/ctypesgen/

I finally got around to looking at this, and it took less than half an
hour to generate working bindings. Obviously, it will need more
testing, but unless any insurmountable problems show up, I intend to
using this in place of SWIG.

Usage is similar to the example posted earlier, except:

1. The library doesn't need to be loaded manually; this is handled by
the wrapper.

2. The GIS_H_VERSION and G_gisinit() macros are wrapped, so you can
just use e.g. "grass.G_gisinit(sys.argv[0])" rather than needing to
extract the version for G__gisinit().

3. The CELL/FCELL/DCELL types are wrapped, so those can be
used instead of c_int, c_float, c_double.

4. The {CELL,FCELL,DCELL}_TYPE constants are wrapped, so those can be
used instead of 0, 1, 2.

The example script is attached.

The wrappers should be largely compatible with those generated by
SWIG, but without the headaches. The automatic type conversions are no
longer there, but converting manually with ctypes is easy enough. 
Also, I've discovered that NumPy arrays have conversion methods, e.g.

    p = buf.ctypes.data_as(POINTER(raster.CELL))

One caveat: this *doesn't* appear to increment the reference count, so
if you do e.g.:

    buf = buf.ctypes.data_as(POINTER(raster.CELL))

the array will be gc'd resulting in buf pointing at garbage.

I've already replaced the SWIG bindings in 7.0 with the ctypesgen

Ideally, I'd like to do the same in 6.x in time for 6.4.0, so that we
can forget that the SWIG version ever existed. The main issue there is
the vdigit and nviz modules in the wxPython GUI (which don't work on
Windows in any case). I haven't tried using ctypesgen for C++, though.

Glynn Clements <glynn at gclements.plus.com>

-------------- next part --------------
#!/usr/bin/env python
import os, sys
from grass.lib import grass, raster
from ctypes import *

input = sys.argv[1]
# determine the inputmap type (CELL/FCELL/DCELL) */
data_type = raster.Rast_map_type(input, "")

if data_type == raster.CELL_TYPE:
    ptype = POINTER(raster.CELL)
elif data_type == raster.FCELL_TYPE:
    ptype = POINTER(raster.FCELL)
elif data_type == raster.DCELL_TYPE:
    ptype = POINTER(raster.DCELL)
infd = raster.Rast_open_old(input, "")
inrast = raster.Rast_allocate_buf(data_type)
inrast = cast(c_void_p(inrast), ptype)

rows = raster.Rast_window_rows()
cols = raster.Rast_window_cols()
for rown in xrange(rows):
    raster.Rast_get_row(infd, inrast, rown, data_type)
    print rown, inrast[0:cols]

More information about the grass-dev mailing list