[GRASS-dev] ctypes problem with Vect_open_old

Hi,

testing simple ctypes script

"""
#!/usr/bin/python

from grass.lib.grass import *
from grass.lib.vector import *

map = Map_info()

Vect_open_old(map, "lakes", "")
"""

I am getting

D1/1: Vect__open_old(): name = (null) mapset = (null) layer= (null) update = 0
Segmentation fault

Seems that strings are getting lost somewhere.

Martin

--
Martin Landa <landa.martin gmail.com> * http://geo.fsv.cvut.cz/~landa

Hi,

2010/12/30 Martin Landa <landa.martin@gmail.com>:

Vect_open_old(map, "lakes", "")

sorry for noise, it should have been

Vect_open_old(byref(map), "lakes", "")

Martin

I was beating my head on same problem till I realized - with ctypes
You just write Your C application in Python. It's still C. When You
start to threat it like C, it works just fine :wink:

Just rumbling,
Maris.

2010/12/30 Martin Landa <landa.martin@gmail.com>:

Hi,

2010/12/30 Martin Landa <landa.martin@gmail.com>:

Vect_open_old(map, "lakes", "")

sorry for noise, it should have been

Vect_open_old(byref(map), "lakes", "")

Martin
_______________________________________________
grass-dev mailing list
grass-dev@lists.osgeo.org
http://lists.osgeo.org/mailman/listinfo/grass-dev

Hi,

2010/12/30 Maris Nartiss <maris.gis@gmail.com>:

I was beating my head on same problem till I realized - with ctypes
You just write Your C application in Python. It's still C. When You
start to threat it like C, it works just fine :wink:

right, just facing to the strange problem, any idea?

Sample script

"""
from grass.lib.vector import *

map_obj = Map_info()
map = pointer(map_obj)

Vect_open_update(map, "a", "")

print Vect_level(map)

p = line_pnts()
Vect_append_point(byref(p), 1, 1, 0)

Vect_write_line(map, GV_POINT, byref(p), None)

Vect_build(map)
Vect_close(map)
"""

$ g.gisenv set=DEBUG=1

D1/3: Vect__open_old(): name = a mapset = layer= (null) update = 1
D1/3: Vect_open_old(): vector opened on level 1
D1/3: Vect_read_dblinks(): map = a, mapset = landa
D3/3: Searching for FID column in OGR DB
D1/3: dbln file: /home/martin/grassdata/nc_spm_08/landa/vector/a/dbln
D1/3: Dblinks read
D1/3: Vect_Rewind(): name = a
1
D3/3: Vect_write_line(): name = (null), format = 170241076, level = 0
ERROR: Unable to write feature, vector map is not opened

The map is opened correctly, Vect_level() works. Anyway
Vect_write_line() fails, seems to be that Map_info is corrupted. No
clue at this moment.

Martin

--
Martin Landa <landa.martin gmail.com> * http://geo.fsv.cvut.cz/~landa

2011/1/4 Martin Landa <landa.martin@gmail.com>:

The map is opened correctly, Vect_level() works. Anyway
Vect_write_line() fails, seems to be that Map_info is corrupted. No
clue at this moment.

when tracking pointer address of Map_info instance -
Vect_open_update() and Vect_level() points to the same address.
Pointer to Map differs in Vect_write_line(), no idea where the pointer
is being corrupted.

Martin

--
Martin Landa <landa.martin gmail.com> * http://geo.fsv.cvut.cz/~landa

2011/1/4 Martin Landa <landa.martin@gmail.com>:

2011/1/4 Martin Landa <landa.martin@gmail.com>:

The map is opened correctly, Vect_level() works. Anyway
Vect_write_line() fails, seems to be that Map_info is corrupted. No
clue at this moment.

when tracking pointer address of Map_info instance -
Vect_open_update() and Vect_level() points to the same address.
Pointer to Map differs in Vect_write_line(), no idea where the pointer
is being corrupted.

strangely e.g. Vect_delete_line() works...

Martin

--
Martin Landa <landa.martin gmail.com> * http://geo.fsv.cvut.cz/~landa

Martin Landa wrote:

right, just facing to the strange problem, any idea?

p = line_pnts()
Vect_append_point(byref(p), 1, 1, 0)

You're passing an uninitialised line_pnts structure (i.e. with its
fields containing garbage), and probably trashing the heap. Use
Vect_new_line_struct() to allocate an empty line_pnts object.

--
Glynn Clements <glynn@gclements.plus.com>

Hi,

2011/1/4 Glynn Clements <glynn@gclements.plus.com>:

p = line_pnts()
Vect_append_point(byref(p), 1, 1, 0)

You're passing an uninitialised line_pnts structure (i.e. with its
fields containing garbage), and probably trashing the heap. Use
Vect_new_line_struct() to allocate an empty line_pnts object.

something like?

map_obj = Map_info()
map = pointer(map_obj)

Vect_open_update(map, "a", "")

p = Vect_new_line_struct()
c = Vect_new_cats_struct()

Vect_append_point(p, 1, 1, 0)
Vect_cat_set(c, 1, 1)
print p.contents.n_points

Vect_write_line(map, GV_POINT, p, c)

Vect_build(map)
Vect_close(map)

No success, btw

p = line_pns()
Vect_append_point(byref(p), 1, 1, 0)
print p.n_points

interestingly works.

Martin

--
Martin Landa <landa.martin gmail.com> * http://geo.fsv.cvut.cz/~landa

This one should work. One has to be really carefull and track when
pointers are required. Working with pointers and ctypes is a tricky
thing.

from ctypes import byref
from grass.lib.vector import *

map = Map_info()

Vect_open_update(byref(map), "vector", "mapset")

p = Vect_new_line_struct()
c = Vect_new_cats_struct()

Vect_append_point(p, 10, 10, 0)

Vect_write_line(byref(map), GV_POINT, p, c)

Vect_build(byref(map))
Vect_close(byref(map))

Maris.

2011/1/4, Martin Landa <landa.martin@gmail.com>:

Hi,

2011/1/4 Glynn Clements <glynn@gclements.plus.com>:

p = line_pnts()
Vect_append_point(byref(p), 1, 1, 0)

You're passing an uninitialised line_pnts structure (i.e. with its
fields containing garbage), and probably trashing the heap. Use
Vect_new_line_struct() to allocate an empty line_pnts object.

something like?

map_obj = Map_info()
map = pointer(map_obj)

Vect_open_update(map, "a", "")

p = Vect_new_line_struct()
c = Vect_new_cats_struct()

Vect_append_point(p, 1, 1, 0)
Vect_cat_set(c, 1, 1)
print p.contents.n_points

Vect_write_line(map, GV_POINT, p, c)

Vect_build(map)
Vect_close(map)

No success, btw

p = line_pns()
Vect_append_point(byref(p), 1, 1, 0)
print p.n_points

interestingly works.

Martin

--
Martin Landa <landa.martin gmail.com> * http://geo.fsv.cvut.cz/~landa

Hi,

2011/1/4 Maris Nartiss <maris.gis@gmail.com>:

This one should work. One has to be really carefull and track when

No, it's not working.

map = Map_info()

Vect_open_update(byref(map), "vector", "mapset")

btw, if you need a pointer (to reuse it), it's better to use pointer()
instead of byref()

map_obj = Map_info()
map = pointer(map_obj)

Vect_open_update(map, "vector", "mapset")

Martin

--
Martin Landa <landa.martin gmail.com> * http://geo.fsv.cvut.cz/~landa

Works here just fine.

GRASS 6.5 r44853
~AMD64 2.6.36
Python 2.6.6 [GCC 4.4.4]

Maris.

2011/1/4, Martin Landa <landa.martin@gmail.com>:

Hi,

2011/1/4 Maris Nartiss <maris.gis@gmail.com>:

This one should work. One has to be really carefull and track when

No, it's not working.

map = Map_info()

Vect_open_update(byref(map), "vector", "mapset")

btw, if you need a pointer (to reuse it), it's better to use pointer()
instead of byref()

map_obj = Map_info()
map = pointer(map_obj)

Vect_open_update(map, "vector", "mapset")

Martin

--
Martin Landa <landa.martin gmail.com> * http://geo.fsv.cvut.cz/~landa

Hi,

2011/1/4 Maris Nartiss <maris.gis@gmail.com>:

Works here just fine.

GRASS 6.5 r44853
~AMD64 2.6.36
Python 2.6.6 [GCC 4.4.4]

right, it seems to be grass7-related issue.

Martin

--
Martin Landa <landa.martin gmail.com> * http://geo.fsv.cvut.cz/~landa

2011/1/4 Martin Landa <landa.martin@gmail.com>:

GRASS 6.5 r44853
~AMD64 2.6.36
Python 2.6.6 [GCC 4.4.4]

right, it seems to be grass7-related issue.

btw, ctypes doesn't work at all in grass65.

Traceback (most recent call last):
  File "/home/martin/smetiste/test3.py", line 2, in <module>
    from grass.lib.vector import *
  File "/usr/local/src/grass6_devel/dist.i686-pc-linux-gnu/etc/python/grass/lib/__init__.py",
line 4, in <module>
    import proj
  File "/usr/local/src/grass6_devel/dist.i686-pc-linux-gnu/etc/python/grass/lib/proj.py",
line 28, in <module>
    _libs["gdal"] = load_library("gdal")
  File "/usr/local/src/grass6_devel/dist.i686-pc-linux-gnu/etc/python/grass/lib/ctypes_loader.py",
line 57, in load_library
    raise ImportError,"%s not found." % libname
ImportError: gdal not found.

Ctypes also doesn't work on Windows, new reason to backport build
system from grass7 to grass65.

Martin

--
Martin Landa <landa.martin gmail.com> * http://geo.fsv.cvut.cz/~landa

Just made a svn up && make distclean && make dance and everything
works just fine, still I'm running GRASS from source directory (no
make install) step.

Maris,
still running 6.5, as 7 (GUI) performance is awfull.

2011/1/4, Martin Landa <landa.martin@gmail.com>:

2011/1/4 Martin Landa <landa.martin@gmail.com>:

GRASS 6.5 r44853
~AMD64 2.6.36
Python 2.6.6 [GCC 4.4.4]

right, it seems to be grass7-related issue.

btw, ctypes doesn't work at all in grass65.

Traceback (most recent call last):
  File "/home/martin/smetiste/test3.py", line 2, in <module>
    from grass.lib.vector import *
  File
"/usr/local/src/grass6_devel/dist.i686-pc-linux-gnu/etc/python/grass/lib/__init__.py",
line 4, in <module>
    import proj
  File
"/usr/local/src/grass6_devel/dist.i686-pc-linux-gnu/etc/python/grass/lib/proj.py",
line 28, in <module>
    _libs["gdal"] = load_library("gdal")
  File
"/usr/local/src/grass6_devel/dist.i686-pc-linux-gnu/etc/python/grass/lib/ctypes_loader.py",
line 57, in load_library
    raise ImportError,"%s not found." % libname
ImportError: gdal not found.

Ctypes also doesn't work on Windows, new reason to backport build
system from grass7 to grass65.

Martin

--
Martin Landa <landa.martin gmail.com> * http://geo.fsv.cvut.cz/~landa

2011/1/4 Maris Nartiss <maris.gis@gmail.com>:

Just made a svn up && make distclean && make dance and everything
works just fine, still I'm running GRASS from source directory (no
make install) step.

same as me.

still running 6.5, as 7 (GUI) performance is awfull.

what do you mean by "GUI performance", probably referring to cairo
driver? Trying to guess. Awfull?

Martin

--
Martin Landa <landa.martin gmail.com> * http://geo.fsv.cvut.cz/~landa

2011/1/4 Martin Landa <landa.martin@gmail.com>:

something like?

map_obj = Map_info()
map = pointer(map_obj)

Vect_open_update(map, "a", "")

p = Vect_new_line_struct()
c = Vect_new_cats_struct()

Vect_append_point(p, 1, 1, 0)
Vect_cat_set(c, 1, 1)
print p.contents.n_points

Vect_write_line(map, GV_POINT, p, c)

Vect_build(map)
Vect_close(map)

No success, btw

seems to be problem with LFS. The script works when GRASS compiled
without LFS. Can anyone confirm it?

Martin

--
Martin Landa <landa.martin gmail.com> * http://geo.fsv.cvut.cz/~landa

Martin Landa wrote:

seems to be problem with LFS. The script works when GRASS compiled
without LFS. Can anyone confirm it?

struct Map_info contains a field of type "struct gvfile", and another
of type "struct Plus_head" which itself contains a field of type
"struct gvfile". "struct gvfile" contains fields of type off_t.

Within grass/lib/vector.py, I have:

  __off_t = c_long # /usr/include/bits/types.h: 141
  
  __off64_t = __quad_t # /usr/include/bits/types.h: 142
  
  off_t = __off64_t # /usr/include/sys/types.h: 90
  
  struct_gvfile._fields_ = [
      ('file', POINTER(FILE)),
      ('start', String),
      ('current', String),
      ('end', String),
      ('size', off_t),
      ('alloc', off_t),
      ('loaded', c_int),
  ]

Here, vector.py is being built with _FILE_OFFSET_BITS=64:

  make[5]: Entering directory `/usr/local/src/grass/7.0/lib/python/ctypes'

  ...

  GISRC=/usr/local/src/grass/7.0/dist.i686-pc-linux-gnu/demolocation/.grassrc70
  GISBASE=/usr/local/src/grass/7.0/dist.i686-pc-linux-gnu
  PATH="/usr/local/src/grass/7.0/dist.i686-pc-linux-gnu/bin:$PATH"
  PYTHONPATH="/usr/local/src/grass/7.0/dist.i686-pc-linux-gnu/etc/python:$PYTHONPATH"
  LD_LIBRARY_PATH="/usr/local/src/grass/7.0/dist.i686-pc-linux-gnu/bin:/usr/local/src/grass/7.0/dist.i686-pc-linux-gnu/lib:/usr/local/src/grass/7.0/dist.i686-pc-linux-gnu/lib:/usr/local/src/grass/svn/dist.i686-pc-linux-gnu/lib"
  LC_ALL=C ./ctypesgen.py --cpp "gcc -E -D_FILE_OFFSET_BITS=64
  -I/usr/local/src/grass/7.0/dist.i686-pc-linux-gnu/include
  -I/usr/local/src/grass/7.0/dist.i686-pc-linux-gnu/include"
  -lgrass_vector.7.0.svn -lgrass_dig2.7.0.svn -lgrass_dgl.7.0.svn
  -lgrass_rtree.7.0.svn -lgrass_linkm.7.0.svn -lgrass_dbmiclient.7.0.svn
  -lgrass_dbmibase.7.0.svn -lgrass_btree2.7.0.svn -lgrass_gproj.7.0.svn
  -I/usr/include -I/usr/include
  /usr/local/src/grass/7.0/dist.i686-pc-linux-gnu/include/grass/vector.h
  /usr/local/src/grass/7.0/dist.i686-pc-linux-gnu/include/grass/vect/dig_structs.h
  /usr/local/src/grass/7.0/dist.i686-pc-linux-gnu/include/grass/vect/dig_defines.h
  -o vector.py

  ...

  Status: gcc -E -D_FILE_OFFSET_BITS=64
  -I/usr/local/src/grass/7.0/dist.i686-pc-linux-gnu/include
  -I/usr/local/src/grass/7.0/dist.i686-pc-linux-gnu/include -U __GNUC__
  -dD -I/usr/include -I/usr/include "-Dinline=" "-D__inline__="
  "-D__extension__=" "-D_Bool=uint8_t" "-D__const=const" "-D__asm__(x)="
  "-D__asm(x)=" "-DCTYPESGEN=1" /home/glynn/.tmp/tmpQU1gtk.h

If the ctypes wrappers weren't built with the same compilation
switches as the libraries which they're trying to wrap, they'll
contain incorrect definitions for off_t and, by extension, anything
which uses it.

If this is happening when the ctypes wrappers and vector libraries are
built at the same time, then we have a problem with our build system.
If it's caused by mixing ctypes wrappers and vector libraries from
different builds (e.g. PYTHONPATH pointing to a different version),
then you need to prevent that.

Note that similar issues apply for C code. If you try to compile a
module which uses the vector library with a different setting of
_FILE_OFFSET_BITS to that used when compiling the library, many of the
structures will have the wrong size and layout. The layout doesn't
matter (unless you access structure fields from your code), but the
size does (i.e. if your code doesn't use LFS but the vector library
does, a variable of type "struct Map_info" will be too small, and the
vector library is likely to overrun it and corrupt whatever follows it
in memory).

--
Glynn Clements <glynn@gclements.plus.com>

Hi,

2011/1/6 Glynn Clements <glynn@gclements.plus.com>:

[...]

If this is happening when the ctypes wrappers and vector libraries are
built at the same time, then we have a problem with our build system.
If it's caused by mixing ctypes wrappers and vector libraries from
different builds (e.g. PYTHONPATH pointing to a different version),
then you need to prevent that.

unfortunately not sure how to fix it. What solution would you suggest?

Martin

--
Martin Landa <landa.martin gmail.com> * http://geo.fsv.cvut.cz/~landa

Martin Landa wrote:

> If this is happening when the ctypes wrappers and vector libraries are
> built at the same time, then we have a problem with our build system.
> If it's caused by mixing ctypes wrappers and vector libraries from
> different builds (e.g. PYTHONPATH pointing to a different version),
> then you need to prevent that.

unfortunately not sure how to fix it. What solution would you suggest?

I'd suggest determining which of the two cases above is actually
occurring.

Add some print statements to the Python script to determine what
PYTHONPATH is set to, whether off_t is an alias for __off_t or
__off64_t, etc.

--
Glynn Clements <glynn@gclements.plus.com>

Hi,

2011/2/4 Glynn Clements <glynn@gclements.plus.com>:

> If this is happening when the ctypes wrappers and vector libraries are
> built at the same time, then we have a problem with our build system.
> If it's caused by mixing ctypes wrappers and vector libraries from
> different builds (e.g. PYTHONPATH pointing to a different version),
> then you need to prevent that.

unfortunately not sure how to fix it. What solution would you suggest?

I'd suggest determining which of the two cases above is actually
occurring.

Add some print statements to the Python script to determine what
PYTHONPATH is set to, whether off_t is an alias for __off_t or
__off64_t, etc.

I put

"""
print os.environ['PYTHONPATH']
print sizeof(off_t)
"""

before calling Vect_open_old() and into vector.py, here is the output

/usr/local/src/grass_trunk/dist.i686-pc-linux-gnu/etc/python
8
/usr/local/src/grass_trunk/dist.i686-pc-linux-gnu/etc/python
8
D1/5: Vect__open_old(): name = (null) mapset = (null) layer= (null) update = 0
Segmentation fault

Martin

--
Martin Landa <landa.martin gmail.com> * http://geo.fsv.cvut.cz/~landa