mapnik / python-mapnik

Python bindings for mapnik
GNU Lesser General Public License v2.1
160 stars 91 forks source link

Crash with old Proj library and ProjTransform() #273

Open hholzgra opened 6 months ago

hholzgra commented 6 months ago

This is somewhat related to issue #246:

Using mapnik.ProjTransform instead of mapnik.Projection to convert from Lat/Long WGS84 to Google Mercator and back works with both old and new Proj library versions, but only when keeping the mapnik.Projection instances that the mapnik.ProjTransform was created from in scope.

When not doing so things work fine on Debian 12 with the new Proj version, but not on Debian 11 that still uses the older Proj version / API.

The following works on both Debian 11 and 12:

import mapnik

try:
    # new Proj library versions (e.g. v9 on Debian 12)
    proj_wgs84  = mapnik.Projection("epsg:4326")
    proj_google = mapnik.Projection("epsg:3857")
except:
    # old Proj libraray versions (e.g. v7 on Debian 11)
    proj_wgs84  = mapnik.Projection("+init=epsg:4326")
    proj_google = mapnik.Projection( "+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 " \
                                     "+lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m   " \
                                     "+nadgrids=@null +no_defs +over")

transform = mapnik.ProjTransform(proj_wgs84, proj_google)

print(transform.forward(mapnik.Coord(8.515900,52.027100)))

But when creating the ProjTransform instance in a function, with the actual Projection instances being local variables that get out of scope at the end of the function, this only works with the new Proj library version on Debian 12, but not with the older one on Debian 11.

So the below code works on 12, but segfaults on the forward() method call on 11:

import mapnik

def get_proj():
    try:
        # new Proj library versions (e.g. v9 on Debian 12)
        proj_wgs84  = mapnik.Projection("epsg:4326") 
        proj_google = mapnik.Projection("epsg:3857")
    except:
        # old Proj libraray versions (e.g. v7 on Debian 11)
        proj_wgs84  = mapnik.Projection("+init=epsg:4326")
        proj_google = mapnik.Projection( "+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 " \
                                         "+lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m   " \
                                         "+nadgrids=@null +no_defs +over")
    return mapnik.ProjTransform(proj_wgs84, proj_google)

transform = get_proj()

print(transform.forward(mapnik.Coord(8.515900,52.027100)))