Не удалось загрузить расширение Spatialite в qSqlite (QT 5.9)

Я пытаюсь загрузить Spatialite как расширение в qSqlite (Qt 5.9), я делал это раньше с Qt4.8, но мне не удалось с QT5.9.
Я изменил sqlite.pri, удалив «SQLITE_OMIT_LOAD_EXTENSION», и внес некоторые изменения в sqlite.c, удалив «#define SQLITE_OMIT_LOAD_EXTENSION 1«и добавление»#define SQLITE_ENABLE_LOAD_EXTENSION 1».
Я также добавляю следующие строки в openDatabase (….)

#if defined(SQLITE_ENABLE_LOAD_EXTENSION)
| SQLITE_LoadExtension|SQLITE_LoadExtFunc
#endif

Теперь «Requet.setQuery (» SELECT load_extension (‘atialite ‘) «, dbProject);» функция распознана, но я получил это сообщение:
ошибка «Указанная процедура не может быть найдена. \ r \ nНе удается получить строку». Если я посмотрю на выходные данные отладки в MSVC14, я увижу, что файл virtualite.dll и все его зависимости загружены.

Обратите внимание: я протестировал это с моим Spatialite, а также с mod_spatialite, который я загружаю с их сайта.

Есть идеи по этой проблеме?
Заранее спасибо.

1

Решение

На примере Вот Я включил пространственный в sqlite, функция включает этот модуль. Для этого необходимо связать библиотеку sqlite3.

Сделанные изменения:

  • + Изменить "SELECT load_extension('libspatialite.so')" в "SELECT load_extension('mod_spatialite')"

  • + Изменить "SELECT InitSpatialMetadata()" в "SELECT InitSpatialMetadata(1)"


#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;
}

Пример:

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();
}

Выход:

**** 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 Arch Linux 4.11.3-1-ARCH, Qt 5.8

2

Другие решения

Спасибо за eyllanesc, я нашел решение благодаря вашим объяснениям и предложениям.

Проблема была с моей скомпилированной библиотекой (все еще я не знаю почему?), А также с mod_spatialite, который я скачал. Этот последний, когда мы используем его с визуальной студией, нужна замена для libstdc++_64-6.dll потому что это приведет к аварии.

Моя проблема была здесь, та, которую я использовал, не была хорошей, и вызывала The specified procedure could not be foundтак я скачал x86_64-5.3.0-release-win32-seh-rt_v4-rev0 и я использовал libstdc++-6.dll (Я изменил название на libstdc++_64-6.dll) с libgcc_s_seh-1.dll, Я также изменил libxml2-2.dll с другим, который я скомпилировал раньше.

Затем я использовал одно из следующих решений:

Решение 1:
Я использовал код раньше с модификацией, потому что ret = sqlite3_exec (db_handle, sql, NULL, NULL, &err_msg); был причиной сбоя, а также я послал БД через параметры, потому что он не работает, как это было в предыдущем коде.

поэтому мой рабочий код сейчас:

#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 \ 3rdparty \ sqlite \» и измените файл sqlite3.c следующим образом:

  1. прокомментировать или удалить #define SQLITE_OMIT_LOAD_EXTENSION 1

  2. добавлять:


#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 следующим образом:

#ifdef SQLITE_ENABLE_LOAD_EXTENSION
| SQLITE_LoadExtension | SQLITE_LoadExtFunc
#endif
  1. снова скомпилируйте ваш плагин, используя ваш компилятор (nmake в моем случае) в Qt5.9.0 \ 5.9 \ Src \ qtbase \ src \ plugins \ sqldrivers \ sqlite \ sqlite.pro

  2. вызовите следующий код для загрузки вашего пространственного объекта:


QSqlQueryModel sql;
sql.setQuery("SELECT load_extension('mod_spatialite')", db);
1

По вопросам рекламы [email protected]