首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >无法加载qSqlite中的空间扩展(QT5.9)

无法加载qSqlite中的空间扩展(QT5.9)
EN

Stack Overflow用户
提问于 2017-06-08 06:09:42
回答 2查看 1.9K关注 0票数 2

我试图在qSqlite ( QT5.9 )中加载Spatialite作为扩展,我以前用Qt4.8做过,但是QT5.9失败了。我通过删除"SQLITE_OMIT_LOAD_EXTENSION“更改了SQLITE_OMIT_LOAD_EXTENSION,并通过删除"#define SQLITE_OMIT_LOAD_EXTENSION 1”和添加"#define SQLITE_ENABLE_LOAD_EXTENSION 1“对sqlite.c进行了一些更改。我还向openDatabase(.)添加了以下行

代码语言:javascript
复制
#if defined(SQLITE_ENABLE_LOAD_EXTENSION)
| SQLITE_LoadExtension|SQLITE_LoadExtFunc
#endif

现在“requet.setQuery(”选择load_extension('spatialite')",dbProject);“函数已被识别,但我收到了这样的消息:错误”,无法找到指定的过程。\r\n如果查看load_extension在MSVC14中的调试输出,我可以看到spatialite.dll及其所有依赖项都已被加载。

注意:我用我的Spatialite和我从他们的网站下载的mod_spatialite测试了这一点。

对这个问题有什么想法吗?提前谢谢。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2017-06-08 14:33:37

感谢eyllanesc,感谢您的解释和建议,我找到了解决方案。

问题在于我的编译库(我仍然不知道为什么?),还有我下载的mod_spatialite。最后一次,当我们在visual中使用它时,需要替换libstdc++_64-6.dll,因为它会导致崩溃。

我的问题就在这里,我使用的问题不是好的,而是导致了The specified procedure could not be found,所以我下载了x86_64-5.3.0-release-win32-seh-rt_v4-rev0,用libgcc_s_seh-1.dll使用了libstdc++-6.dll (改名为libstdc++_64-6.dll)。我还用我以前编译的另一个libxml2-2.dll修改了它。

然后,我使用了以下解决方案之一:

解决方案1:在修改之前使用了代码,因为ret = sqlite3_exec (db_handle, sql, NULL, NULL, &err_msg);会导致崩溃,而且我通过参数发送db,因为它的工作方式不像以前的代码那样工作。

所以我现在的工作代码是:

代码语言:javascript
复制
#include <QtCore/QCoreApplication>
#include <QtSql/QtSql>
#include "sqlite3.h"

int enable_spatialite(QSqlDatabase db) {
    QVariant v = db.driver()->handle();
    if (v.isValid() && qstrcmp(v.typeName(), "sqlite3*") == 0)
    {
        sqlite3_initialize();
        sqlite3 *db_handle = *static_cast<sqlite3 **>(v.data());

        if (db_handle != 0) {

            sqlite3_enable_load_extension(db_handle, 1);

            QSqlQueryModel sql;
            sql.setQuery("SELECT load_extension('mod_spatialite')", db);
            if (sql.lastError().isValid())
            {
                qDebug() << "Error: cannot load the Spatialite extension (" << sql.lastError().text()<<")";
                return 0;
            }
            else    return 1;
        }
    }
    return 0;
}

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE", "Project");
    db.setDatabaseName("dbTest.db");
    if (!db.open())
    {
        qDebug()<<"Critical"<< "Impossible to intialize the database !\n" + db.lastError().text();
        return 0;
    }
    qDebug()<<enable_spatialite(db);

    //just a test
    QSqlQueryModel sql;
    sql.setQuery("SELECT HEX(GeomFromText('POINT(10 20)'));", db);
    qDebug() << sql.index(0, 0).data().toString();

    return a.exec();
}

还有一件重要的事情是,我重新编译了qsqlite驱动程序以删除SQLITE_OMIT_LOAD_EXTENSION。

解决方案2:(直接解决)

打开“Qt5.9.0\5.9\src\qtbase\src\3 3rdparty\sqlite\”文件夹,并将sqlite3.c更改如下:

  1. 注释或删除#define SQLITE_OMIT_LOAD_EXTENSION 1
  2. 加:
代码语言:javascript
复制
#ifndef SQLITE_ENABLE_LOAD_EXTENSION
#define SQLITE_ENABLE_LOAD_EXTENSION 1
#endif 
  1. 转到static int openDatabase( const char *zFilename,sqlite3 **ppDb, unsigned int flags, const char *zVfs)函数并将| SQLITE_LoadExtFunc添加到SQLITE_ENABLE_LOAD_EXTENSION中,如下所示:
代码语言:javascript
复制
#ifdef SQLITE_ENABLE_LOAD_EXTENSION
                 | SQLITE_LoadExtension | SQLITE_LoadExtFunc
#endif 
  1. 在Qt5.9.0\5.9\Src\qtbase\src\plugins\sqldrivers\sqlite\sqlite.pro中再次使用编译器(在我的例子中是nmake )编译插件
  2. 调用以下代码加载空间站点:
代码语言:javascript
复制
QSqlQueryModel sql;
sql.setQuery("SELECT load_extension('mod_spatialite')", db); 
票数 2
EN

Stack Overflow用户

发布于 2017-06-08 10:06:04

基于示例这里,我启用了sqlite中的spatialite,该函数启用了该模块。要做到这一点,您必须链接sqlite3库。

所作的修改如下:

  • "SELECT load_extension('libspatialite.so')"更改为"SELECT load_extension('mod_spatialite')"
  • "SELECT InitSpatialMetadata()"更改为"SELECT InitSpatialMetadata(1)"
代码语言:javascript
复制
#include <sqlite3.h>
#include <QSqlDatabase>
#include <QSqlDriver>
#include <QSqlError>

int enable_spatialite(QSqlDatabase db){
    QVariant v = db.driver()->handle();
    if (v.isValid() && qstrcmp(v.typeName(), "sqlite3*")==0)
    {
        sqlite3_initialize();
        sqlite3 *db_handle = *static_cast<sqlite3 **>(v.data());

        if (db_handle != 0) {
            sqlite3_enable_load_extension(db_handle, 1);

            QSqlQuery query;

            query.exec("SELECT load_extension('mod_spatialite')");
            if (query.lastError() .isValid())
            {
                qDebug() << "Error: cannot load the Spatialite extension (" << query.lastError().text()<<")";
                return 0;
            }

            qDebug()<<"**** SpatiaLite loaded as an extension ***";

            query.exec("SELECT InitSpatialMetadata(1)");
            if (query.lastError() .isValid())
            {
                qDebug() << "Error: cannot load the Spatialite extension (" << query.lastError().text()<<")";
                return 0;
            }
            qDebug()<<"**** InitSpatialMetadata successful ***";

            return 1;
        }
    }
    return 0;
}

示例:

代码语言:javascript
复制
int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    QSqlDatabase db =  QSqlDatabase::addDatabase("QSQLITE");

    db.setDatabaseName("memory.db");
    if (!db.open()) {
        qDebug()<<"not open";
    }

    qDebug()<<enable_spatialite(db);

    QSqlQuery query;

    qDebug()<<query.exec("CREATE TABLE test_geom (id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL, measured_value DOUBLE NOT NULL);");
    qDebug()<<query.exec("SELECT AddGeometryColumn('test_geom', 'the_geom', 4326, 'POINT', 'XY');");



    for(int i=0; i< 10; i++){
        QString q = QString("INSERT INTO test_geom(id, name, measured_value, the_geom) VALUES (%1,'point %2', %3, GeomFromText('POINT(1.01 2.02)', 4326))")
                .arg("NULL").arg(i).arg(i);
        query.prepare(q);
        qDebug()<< i<<query.exec();
    }

    qDebug()<<query.exec("SELECT id, name, measured_value,  AsText(the_geom), ST_GeometryType(the_geom), ST_Srid(the_geom) FROM test_geom");


    while (query.next()) {
        QString str;
        for(int i=0; i < query.record().count(); i++)
            str += query.value(i).toString() + " ";
        qDebug()<<str;
    }
    return a.exec();
}

输出:

代码语言:javascript
复制
**** SpatiaLite loaded as an extension ***
**** InitSpatialMetadata successful ***
1
true
true
0 true
1 true
2 true
3 true
4 true
5 true
6 true
7 true
8 true
9 true
true
"1 point 0 0 POINT(1.01 2.02) POINT 4326 "
"2 point 1 1 POINT(1.01 2.02) POINT 4326 "
"3 point 2 2 POINT(1.01 2.02) POINT 4326 "
"4 point 3 3 POINT(1.01 2.02) POINT 4326 "
"5 point 4 4 POINT(1.01 2.02) POINT 4326 "
"6 point 5 5 POINT(1.01 2.02) POINT 4326 "
"7 point 6 6 POINT(1.01 2.02) POINT 4326 "
"8 point 7 7 POINT(1.01 2.02) POINT 4326 "
"9 point 8 8 POINT(1.01 2.02) POINT 4326 "
"10 point 9 9 POINT(1.01 2.02) POINT 4326 "

完整的示例可以找到这里

此代码已在linux 4.11.3-1- Arch,QT5.8上进行了测试。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/44427868

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档