我将开始使用PyQt5及其sqlite的Sql类。我想将扩展加载到sqlite中。为此,必须在运行时为sqlite启用扩展加载。在python模块sqlite3中,这是通过enable_load_扩展启用的。
在C中,sqlite
句柄可以这样获得(取自https://doc.qt.io/qt-5/qsqldriver.html#handle):
QSqlDatabase db = QSqlDatabase::database();
QVariant v = db.driver()->handle();
if (v.isValid() && (qstrcmp(v.typeName(), "sqlite3*") == 0)) {
// v.data() returns a pointer to the handle
sqlite3 *handle = *static_cast<sqlite3 **>(v.data());
if (handle) {
// ...
}
}
python的等价物是
from PyQt5.QtSql import QSqlDatabase
db = QSqlDatabase.addDatabase('QSQLITE')
db.driver().handle()
-> TypeError: unable to convert a C++ 'sqlite3*' instance to a Python object
作为旁注,在Pyside2中,handle方法没有公开。
看来这样做是不对的。有没有办法通过PyQt5加载sqlite扩展?
一种可能的解决方案是创建一个使用ctypes加载的库。
在本例中,我展示了ubuntu linux的解决方案,但我认为类似的步骤也可以应用于其他操作系统
qsqlite。赞成的意见
QT -= gui
QT += sql
TEMPLATE = lib
DEFINES += QSQLITE_LIBRARY
CONFIG += unversioned_libname unversioned_soname
CONFIG += c++11
SOURCES += \
qsqlite.cpp
HEADERS += \
qsqlite_global.h \
qsqlite.h
LIBS += -lsqlite3
qsqlite_全球。H
#ifndef QSQLITE_GLOBAL_H
#define QSQLITE_GLOBAL_H
#if defined(_MSC_VER) || defined(WIN64) || defined(_WIN64) || defined(__WIN64__) || defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__)
# define Q_DECL_EXPORT __declspec(dllexport)
# define Q_DECL_IMPORT __declspec(dllimport)
#else
# define Q_DECL_EXPORT __attribute__((visibility("default")))
# define Q_DECL_IMPORT __attribute__((visibility("default")))
#endif
#if defined(QSQLITE_LIBRARY)
# define QSQLITE_EXPORT Q_DECL_EXPORT
#else
# define QSQLITE_EXPORT Q_DECL_IMPORT
#endif
#endif // QSQLITE_GLOBAL_H
qsqlite。H
#ifndef QSQLITE_H
#define QSQLITE_H
#include "qsqlite_global.h"
class QSqlDriver;
extern "C" {
bool QSQLITE_EXPORT enable_extension(QSqlDriver *ptr, bool enabled);
}
#endif // QSQLITE_H
qsqlite.cpp
#include "qsqlite.h"
#include <sqlite3.h>
#include <QSqlDriver>
#include <QVariant>
bool enable_extension(QSqlDriver *driver, bool enabled)
{
if(!driver)
return false;
QVariant v = driver->handle();
if (!v.isValid() || !(qstrcmp(v.typeName(), "sqlite3*")==0))
return false;
if(sqlite3 *db_handle = *static_cast<sqlite3 **>(v.data())){
sqlite3_initialize();
sqlite3_enable_load_extension(db_handle, enabled);
return true;
}
return false;
}
qsqlite/
├── qsqlite.cpp
├── qsqlite_global.h
├── qsqlite.h
└── qsqlite.pro
要编译,您必须使用Qt,所以在这种情况下,我将通过执行以下命令来使用aqt安装(python-m pip安装aqt安装
):
python -m aqt install 5.15.0 linux desktop --outputdir qt
qt/5.15.0/gcc_64/bin/qmake qsqlite
make
注意:要编译库,必须有sqlite3的头文件,为此,您必须在ubuntu中使用libsqlite3-dev
安装:sudo-apt-install-y——没有安装建议使用libsqlite3-dev
。
这将创建libqsqlite。因此,必须复制到脚本旁边的库,例如,以下代码加载spatialite模块(sudo apt install-y——无安装建议libsqlite3 mod spatialite
)。
主要的派克
from ctypes import CDLL, c_void_p
import os
from PyQt5.QtSql import QSqlDatabase, QSqlQuery
import sip
CURRENT_DIR = os.path.dirname(os.path.realpath(__file__))
def load_spatialite():
queries = (
"SELECT load_extension('mod_spatialite')",
"SELECT InitSpatialMetadata(1)",
)
q = QSqlQuery()
for query in queries:
if not q.exec_(query):
print(
f"Error: cannot load the Spatialite extension ({q.lastError().text()})"
)
return False
return True
def main():
db = QSqlDatabase.addDatabase("QSQLITE")
db.setDatabaseName("foo.sqlite")
if not db.open():
sys.exit(-1)
lib = CDLL(os.path.join(CURRENT_DIR, "libqsqlite.so"))
lib.enable_extension(c_void_p(sip.unwrapinstance(db.driver()).__int__()), True)
load_spatialite()
query = QSqlQuery()
query.exec_("CREATE TABLE my_line(id INTEGER PRIMARY KEY)")
query.exec_(
"""SELECT AddGeometryColumn("my_line","geom" , 4326, "LINESTRING", 2)"""
)
polygon_wkt = "POLYGON ((11 50,11 51,12 51,12 50,11 50))"
XA = 11
YA = 52
XB = 12
YB = 49
line_wkt = "LINESTRING({0} {1}, {2} {3})".format(XA, YA, XB, YB)
query.prepare("""INSERT INTO my_line VALUES (?,GeomFromText(?, 4326))""")
query.addBindValue(1)
query.addBindValue(line_wkt)
query.exec_()
query.prepare(
"""SELECT astext(st_intersection(geom, GeomFromText(?, 4326))) from my_line WHERE st_intersects(geom, GeomFromText(?, 4326))"""
)
query.addBindValue(polygon_wkt)
query.addBindValue(polygon_wkt)
query.exec_()
while query.next():
for i in range(query.record().count()):
print(query.value(i))
if __name__ == "__main__":
main()
├── main.py
└── libqsqlite.so
输出:
LINESTRING(11.333333 51, 11.666667 50)
PySide2可以使用相同的库:
from ctypes import CDLL, c_void_p
import os
from PySide2.QtSql import QSqlDatabase, QSqlQuery
import shiboken2
CURRENT_DIR = os.path.dirname(os.path.realpath(__file__))
def load_spatialite():
queries = (
"SELECT load_extension('mod_spatialite')",
"SELECT InitSpatialMetadata(1)",
)
q = QSqlQuery()
for query in queries:
if not q.exec_(query):
print(
f"Error: cannot load the Spatialite extension ({q.lastError().text()})"
)
return False
return True
def main():
db = QSqlDatabase.addDatabase("QSQLITE")
db.setDatabaseName("foo.sqlite")
if not db.open():
sys.exit(-1)
lib = CDLL(os.path.join(CURRENT_DIR, "libqsqlite.so"))
lib.enable_extension(c_void_p(shiboken2.getCppPointer(db.driver())[0]))
load_spatialite()
query = QSqlQuery()
query.exec_("CREATE TABLE my_line(id INTEGER PRIMARY KEY)")
query.exec_(
"""SELECT AddGeometryColumn("my_line","geom" , 4326, "LINESTRING", 2)"""
)
polygon_wkt = "POLYGON ((11 50,11 51,12 51,12 50,11 50))"
XA = 11
YA = 52
XB = 12
YB = 49
line_wkt = "LINESTRING({0} {1}, {2} {3})".format(XA, YA, XB, YB)
query.prepare("""INSERT INTO my_line VALUES (?,GeomFromText(?, 4326))""")
query.addBindValue(1)
query.addBindValue(line_wkt)
query.exec_()
query.prepare(
"""SELECT astext(st_intersection(geom, GeomFromText(?, 4326))) from my_line WHERE st_intersects(geom, GeomFromText(?, 4326))"""
)
query.addBindValue(polygon_wkt)
query.addBindValue(polygon_wkt)
query.exec_()
while query.next():
for i in range(query.record().count()):
print(query.value(i))
if __name__ == "__main__":
main()
对于测试,我使用了你可以在这里找到的docker。
扩展说明 扩展点本身的加载容器,可从不同容器加载扩展点。 扩展接口 org.apache.dubbo.common.extension.ExtensionFactory 扩展配置 <dubbo:application compiler="jdk" /> 已知扩展 org.apache.dubbo.common.extension.factory.SpiExtensionFactory org.a
扩展点配置 来源: Dubbo 的扩展点加载从 JDK 标准的 SPI (Service Provider Interface) 扩展点发现机制加强而来。 Dubbo 改进了 JDK 标准的 SPI 的以下问题: JDK 标准的 SPI 会一次性实例化扩展点所有实现,如果有扩展实现初始化很耗时,但如果没用上也加载,会很浪费资源。 如果扩展点加载失败,连扩展点的名称都拿不到了。比如:JDK 标准的
我在phpinfo()中的“已解析的其他.ini文件”部分看不到mcryptphp_mcrypt'已经安装。我使用CentOs和nginx以及PHP5.3。3. 在/etc/php中。d/mcrypt。我写的ini扩展名=mcrypt。所以 我试图改变扩展路径在php.ini(ex扩展=/usr/lib64/php/模块/mcrypt.so),但它仍然不工作。
这里有一个总节点noob。我一直在尝试设置示例节点应用程序,但每次尝试运行时都会出现以下错误: 节点应用程序
我正在windows server 2008 R2机器上工作。我已经用PHP5.4安装了Apache2.2。25在尝试为apache服务器启用ldap支持时,我发现服务器没有加载扩展。 我跑了php_info(),结果是这样的 配置文件(php.ini)路径 C:\Windows加载的配置文件:“C:\php\php.ini 扩展目录C:\php\ext 我已经改变了php。ini加载扩展,但它们
我有一个问题加载我的扩展在PHP在windows 7.我已经在我的windows上安装了php和IIS,当我检查phpinfo()页面时,我发现我的extension_dir是c:/php/exts。所以我将我的dll文件复制到那个目录中,并添加php.ini文件,然后我重启IIS并检查我的扩展名是否已加载: 但每次我运行这段代码时都会得到“否”。谢谢你的帮助。