当前位置: 首页 > 工具软件 > SpatiaLite > 使用案例 >

spatialite扩展的编译和安装

端木野
2023-12-01

spatialite作为一个sqlite3数据库的extension,使得sqlite3具有地理空间数据的处理能力。
spatialite在linux上的编译,中文资料太少了。在此记录一下编译及使用过程。

开始

编译依赖库!没错,spatialite依赖了很多很多库。列举如下(直接粘贴了我cmakelist的内容):

#libproj.a
find_library(Proj_LIBRARY NAMES libproj.a)
link_libraries(${Proj_LIBRARY})
MESSAGE(proj_lib:${Proj_LIBRARY})
#geos_c.a
find_library(geos_c_library NAMES libgeos_c.a)
link_libraries(${geos_c_library})
MESSAGE(geos_c_lib:${geos_c_library})
find_library(geos_library NAMES geos)
link_libraries(${geos_library})
MESSAGE(geos_lib:${geos_library})
#freexl.a
find_library(freexl_library NAMES libfreexl.a)
link_libraries(${freexl_library})
MESSAGE(freexl_lib:${freexl_library})
#xml2.a
find_library(xml2_library NAMES libxml2.a )
link_libraries(${xml2_library})
MESSAGE(xml2_lib:${xml2_library})
#libiconv
find_library(iconv_library NAMES libiconv.a )
link_libraries(${iconv_library})
MESSAGE(iconv_lib:${iconv_library})
#libz
find_library(z_library NAMES libz.a )
link_libraries(${z_library})
MESSAGE(z_library:${z_library})
#libzma
find_library(lzma_library NAMES liblzma.a )
link_libraries(${lzma_library})
MESSAGE(lzma_library:${lzma_library})
link_libraries( libm.a pthread dl libc.a)

proj,geos,freexl,xml2,iconv,z,lzma,m,pthred,dl,c
除了m,pthread,dl,c是标准库,其他的都需要自行编译。


依赖库的编译,此处不做详细描述了。方法大同小异:

  1. 下载源码(注意版本)http://www.gaia-gis.it/gaia-sins/libspatialite-sources/
  2. 进入源码文件夹
  3. $./configure --prefix="安装目录!" --enable-static=yes CXXFLAGS=-fPIC CFLAGS=-fPIC
  4. $sudo make
  5. $sudo make install

spatialite的编译过程与上面步骤相同。编译完成后,会生成 libspatialite.so,libspatialite.a,mod_spatialite.so
这个mod开头的是个啥呢?官方原文如下:

What's new in mod_spatialite

You'll probably be already accustomed to load SpatiaLite as a dynamic extension; but any previous version before 4.2 made no real distinction between loadable modules and general-purpose shared libraries.
As we painfully learned by direct on-the-field experience, this apparently simpler configuration caused lot of troubles: instabilities, sudden crashes and so on. Making a clearer distinction between a general-purpose shared library and a pure loadable module seems to be the definitive solution.
Exactly here is the radical innovation introduce starting since version 4.2; now SpatiaLite is distributed in two alternative flavors:

  • libspatialite (.so, .dll, .dylib and so on): a genuine classic shared library.
    It will always depend on some external libsqlite3, and is uniquely intended to be used by stand-alone applications (such as e.g. spatialite or spatialite_gui).
    You'll never be able to successfully load this libspatialite shared library as a dynamic extension via the SELECT load_extension mechanism, simply because it doesn't declare the required conventional interface.
  • mod_spatialite (.so, .dll, .dylib and so on): this is simply intended as pure loadable module lacking any explicit SQLite3 dependency.
    You'll never be able to directly link this mod_spatialite shared library following the classic way, because it doesn't declare any external link symbol except that a single one: i.e. the conventional interface. The unique possible way to load and activate this module is by calling a SELECT load_extension SQL statement.

总而言之,言而总之:libspatialite可以用作项目的依赖库。mod_spatialite不可以!
mod_spatialite是sqlite3的extension,可以通过sqlite3_load_extesiong接口动态加载。如果你要使用这个方式去使用spatialite,那就用这个吧。
我使用的方式是忽略mod_spatialite,正常使用libspatialite.a。
接下啦,在项目中正常添加libspatialite.a就可以啦。在cmakelist中添加:

 

#sqlite3/spatialite
find_path(Spatialite_INCLUDE_DIR NAMES spatialite.h)
find_library(Spatialite_LIBRARY libspatialite.a)
include_directories(${Spatialite_INCLUDE_DIR})
link_libraries(${Spatialite_LIBRARY})
MESSAGE(spatialite_lib:${Spatialite_LIBRARY})
MESSAGE(spatialite_include:${Spatialite_INCLUDE_DIR})
#sqlite3secure.a 这是一个sqlite3的加密库!!!!!
find_library(Sqlite3Secure_LIBRARY NAMES libsqlite3secure.a)
link_libraries(${Sqlite3Secure_LIBRARY})
MESSAGE(sqlite3secure_lib:${Sqlite3Secure_LIBRARY})

使用

  1. 官方提供了一些demo:http://www.gaia-gis.it/gaia-sins/splite-doxy-4.3.0/examples.html
    需要注意的是,官方给的例子是使用sqlite3_load_extension来动态加载spatialite。

  2. 以下是我使用的方法
    使用了sqlite3pp

#include <sqlite3.h>
#include <spatialite/gaiageo.h>
#include <spatialite.h>
...
...
    gaiaVectorLayerPtr lyr;
    LaneMarkingInfo* lmarking = nullptr;
    auto handle = SqliteSingleton::getInstance();
    stringstream ss;
    ss << "SELECT marking_id, marking_type, marking_color,marking_material, marking_width ,CastToLinestring(geometry)  FROM hd_lane_marking ";
    ss << " WHERE ROWID IN (SELECT pkid FROM idx_hd_lane_marking_geometry WHERE xmin > " << rcBound.left;
    ss << " and xmax < " << rcBound.right;
    ss << " and ymin > " << rcBound.bottom;
    ss << " and ymax <" << rcBound.top << ")";
    sqlite3pp::query qry(*handle.get(),ss.str().c_str());

    gaiaLinestringPtr geom;
    for (auto i = qry.begin(); i != qry.end(); ++i) {
        lmarking = new LaneMarkingInfo;
        lmarking->nId = (*i).get<long long>(0);
        lmarking->nShape = (*i).get<int32_t>(1);
        lmarking->nColor = (*i).get<int32_t>(2);
        lmarking->nMaterial = (*i).get<int32_t>(3);
        lmarking->nWidth = (*i).get<int32_t>(4);
        const unsigned char* pBuf = (const unsigned char*)(*i).get<const char*>(5);
        int nBlobSize = (*i).column_bytes(5);
        geom = gaiaFromSpatiaLiteBlobWkb(pBuf, nBlobSize)->FirstLinestring;
        int nCount = geom->Points;

        Point3D* pts = new Point3D[nCount];
        for (int i =0; i <  nCount; i++)
        {
            pts[i].x = geom->Coords[2 * i];
            pts[i].y = geom->Coords[2 * i + 1];
            pts[i].z = 0;
        }
        lmarking->pPts = pts;
        lmarking->nCount = nCount;
        listObj.push_back(lmarking);
        gaiaFreeLinestring(geom);
    }
    return true;

总结:

说到底,编译使用的过程都很简单。困难与痛苦的地方在于查资料。

 类似资料: