新闻详情

新闻详情

首页 / 资讯中心 / 详情

QGIS 3.6.1 二次开发包:环境配置、调试与避坑指南

发布时间:2026/9/29 16:44:39来源:尧图网络
QGIS 3.6.1 二次开发包:环境配置、调试与避坑指南
简介这份资源是面向地理信息系统开发者的QGIS 3.6.1二次开发包专为希望在Windows 10环境下基于Visual Studio 2015构建自定义插件或集成QGIS功能的开发者准备免去了自行编译源码的繁琐流程。压缩包为zip格式整体约69.99MB内含预编译库文件、C头文件、示例代码、API文档、构建脚本及pdb调试符号等其中库文件与头文件用于项目引用和接口调用示例与文档帮助理解QGIS API用法调试资源则支持源码级排错。资源标签中的qgis debug提示其包含调试信息便于追踪代码执行步骤、定位核心库或自研代码中的问题。目前已有699人学习下载适合具备一定C与Qt基础、需要快速搭建QGIS二次开发环境的中高级开发者参考使用。1. QGIS 3.6.1 二次开发包为什么老版本反而成了刚需如果你最近在配 QGIS 的 C 或 Python 二次开发环境大概率已经发现一个反直觉的现象越新的版本越难搞。QGIS 3.6.1 这个 2019 年的版本反而成了不少团队锁死的开发基线。原因不复杂——它的 API 相对稳定依赖链短编译工具链要求低而且大量存量插件和内部工具都是基于这个版本写的。你拿 3.28 或 3.34 去跑老代码光是QgsGeometry的接口变动就够你改半天。这份二次开发包解决的核心问题就一个让你在 Windows 上快速拿到一套可编译、可调试、可二次开发的 QGIS 3.6.1 环境不用从源码开始啃 CMake 和 OSGeo4W。它适合两类人一是需要基于 QGIS 做桌面端定制开发的 C 工程师二是用 PyQGIS 写自动化脚本但被环境问题反复折磨的 GIS 从业者。关键词里那个qgis debug不是随便加的——这套包的价值恰恰在于调试链路是通的你能断点进 QGIS 源码而不是对着黑匣子猜。2. 二次开发包拆开看目录结构、依赖与编译链路2.1 包里到底有什么拿到一个二次开发包第一件事不是急着编译而是先看清楚它的组织方式。常见的 QGIS 3.6.1 开发包一般包含这几块编译好的qgis_core.dll、qgis_gui.dll及其对应的.lib导入库和头文件目录OSGeo4W 的运行时依赖GDAL、PROJ、GEOS、SQLite 等以及一套 CMake 配置文件让你在自己的项目里find_package(QGIS)就能定位到这些路径。我一般会先跑一遍目录树确认三件事头文件版本号是否和 DLL 对得上、依赖库是否齐全、有没有附带.pdb调试符号文件。最后这点直接决定你能不能做qgis debug。没有 pdb你只能看到调用栈的地址看不到函数名和行号调试体验约等于盲人摸象。# 查看开发包顶层结构确认关键目录是否存在 tree -L 2 -d qgis-3.6.1-dev/ # 典型输出应包含 # include/ - 头文件 # lib/ - .lib 导入库 # bin/ - .dll 运行时 .pdb 调试符号 # share/ - 资源文件srs.db、坐标系定义等 # cmake/ - CMake 配置文件这里include/下应该能看到qgis_core.h、qgsapplication.h这类核心头文件。bin/里除了 DLL重点看有没有qgis_core.pdb、qgis_gui.pdb。如果包是 Release 编译的pdb 可能只包含公开符号但至少能让你在调试器里看到函数名。share/目录别忽略——QGIS 启动时要加载srs.db做坐标转换路径配错了程序直接崩而且报错信息往往很含糊。2.2 环境变量与 CMake 集成Windows 上做 QGIS 二次开发环境变量是第一个拦路虎。QGIS 运行时依赖一堆 DLL你不把bin目录加进PATH编译能过一运行就提示找不到gdal306.dll之类的。我习惯在项目里写一个env.bat把该设的一次性设好避免每次开终端都手动配。:: env.bat - QGIS 3.6.1 开发环境变量 echo off set QGIS_PREFIX_PATHD:\dev\qgis-3.6.1-dev set PATH%QGIS_PREFIX_PATH%\bin;%PATH% set GDAL_DATA%QGIS_PREFIX_PATH%\share\gdal set PROJ_LIB%QGIS_PREFIX_PATH%\share\proj :: 调试时让系统优先加载开发包里的 DLL而不是系统目录里的旧版本 set QGIS_DEBUG1QGIS_PREFIX_PATH是 QGIS 内部用来定位插件和资源的根路径很多初始化失败都是因为它没设或设错了。GDAL_DATA和PROJ_LIB分别指向坐标系统和投影定义的数据库目录缺了这两个你加载矢量数据时坐标系会识别成 Unknown。QGIS_DEBUG1会打开 QGIS 内部的调试日志输出排查初始化问题时非常有用。CMake 这边开发包通常会提供一个QGISConfig.cmake或FindQGIS.cmake。你的CMakeLists.txt里这样写cmake_minimum_required(VERSION 3.10) project(MyQgisPlugin) # 指向开发包提供的 cmake 配置目录 list(APPEND CMAKE_PREFIX_PATH D:/dev/qgis-3.6.1-dev) find_package(QGIS REQUIRED COMPONENTS Core Gui) add_executable(my_app main.cpp) target_link_libraries(my_app PRIVATE QGIS::Core QGIS::Gui)find_package的COMPONENTS指定你要链接的模块一般至少需要Core和Gui。如果你的工具涉及地图渲染还要加Widgets或3D3.6.1 的 3D 模块还比较早期慎用。target_link_libraries用现代 CMake 的 imported target 写法比手动拼-lqgis_core干净得多也能自动带上依赖传递。2.3 一个最小可运行的初始化代码环境配好之后写个最小程序验证链路是否通。QGIS 的 C API 初始化有一套固定流程先创建QgsApplication再初始化库路径最后才能用其他功能。// main.cpp - 最小 QGIS 3.6.1 初始化验证 #include qgsapplication.h #include qgsproviderregistry.h #include iostream int main(int argc, char *argv[]) { // 第三个参数 true 表示启用 GUI纯后台处理可以传 false QgsApplication app(argc, argv, true); // 设置插件路径指向开发包的 plugins 目录 QgsApplication::setPluginPath( QStringLiteral(D:/dev/qgis-3.6.1-dev/bin/plugins)); QgsApplication::initQgis(); // 打印已注册的数据提供者验证 GDAL/OGR 是否加载成功 QStringList providers QgsProviderRegistry::instance()-providerList(); std::cout Loaded providers: providers.join(, ).toStdString() std::endl; QgsApplication::exitQgis(); return 0; }QgsApplication的构造函数第三个参数控制是否初始化 GUI 相关资源如果你只做数据处理传false能省掉不少启动开销。setPluginPath必须在initQgis()之前调用否则 QGIS 会去默认路径找插件找不到就静默跳过。providerList()返回的是当前可用的数据提供者列表正常情况下你应该能看到ogr、gdal、postgres等。如果列表是空的说明 GDAL 的插件 DLL 没被正确加载回去检查PATH和QGIS_PREFIX_PATH。3. 用 PyQGIS 做二次开发脚本层的落地路径3.1 Python 环境怎么接进 QGIS 3.6.1不是所有人都需要写 C。大量二次开发需求——批量处理、自动化出图、数据质检——用 PyQGIS 就够了开发效率高一个数量级。但 PyQGIS 的环境配置有个坑你不能用系统里随便一个 Python必须用 QGIS 自带的那个或者至少保证sys.path能指向 QGIS 的python目录。QGIS 3.6.1 在 Windows 上通常自带 Python 3.7。开发包的bin目录下会有python-qgis.bat之类的启动脚本它帮你把PYTHONPATH和PATH都设好了。我一般直接用这个脚本起交互环境省得自己配。# 验证 PyQGIS 环境是否可用 from qgis.core import QgsApplication, QgsVectorLayer # 初始化 QGIS第二个参数 False 表示不启用 GUI qgs QgsApplication([], False) qgs.initQgis() # 加载一个 shapefile 测试数据提供者 layer QgsVectorLayer(D:/data/test.shp, test, ogr) if layer.isValid(): print(f要素数量: {layer.featureCount()}) print(f坐标系: {layer.crs().authid()}) else: print(图层加载失败检查路径和 GDAL 驱动) qgs.exitQgis()QgsApplication([], False)里的空列表是argv脚本模式下不需要命令行参数。initQgis()会加载所有数据提供者插件这一步如果卡住或报错通常是PATH里缺了某个依赖 DLL。QgsVectorLayer的第三个参数ogr指定用 OGR 驱动这是最通用的矢量数据提供者shapefile、GeoJSON、GPKG 都走它。layer.isValid()返回False时先别怀疑代码用ogrinfo命令行工具确认数据本身能不能打开。3.2 用 Processing 框架跑空间分析PyQGIS 真正省事的地方在于能直接调 Processing 框架里的算法。缓冲区、相交、裁剪这些操作你不需要自己写几何运算一行processing.run()就搞定。但 3.6.1 的 Processing 初始化方式和后续版本略有不同需要手动把算法提供者注册进去。# 使用 Processing 框架做缓冲区分析 from qgis.core import QgsApplication, QgsVectorLayer, QgsProcessingFeedback from qgis.analysis import QgsNativeAlgorithms import processing qgs QgsApplication([], False) qgs.initQgis() # 注册原生算法提供者3.6.1 必须手动加这一步 from processing.core.Processing import Processing Processing.initialize() QgsApplication.processingRegistry().addProvider(QgsNativeAlgorithms()) # 输入图层 input_layer QgsVectorLayer(D:/data/roads.shp, roads, ogr) # 缓冲区分析距离 100 米分段数 5 result processing.run(native:buffer, { INPUT: input_layer, DISTANCE: 100, SEGMENTS: 5, END_CAP_STYLE: 0, # 0圆头 JOIN_STYLE: 0, # 0圆角 DISSOLVE: False, OUTPUT: D:/data/roads_buffer.shp }, feedbackQgsProcessingFeedback()) print(f输出文件: {result[OUTPUT]}) qgs.exitQgis()Processing.initialize()和addProvider(QgsNativeAlgorithms())这两步在 3.6.1 里缺一不可少了任何一个processing.run都会报Algorithm not found。native:buffer的参数名在不同版本间有变化3.6.1 用的是DISTANCE而不是DISTANCE_VALUE这个差异在查文档时要注意版本对应。SEGMENTS控制圆弧的平滑度值越大越平滑但计算越慢一般 5 到 8 够用。DISSOLVE设为True会把所有缓冲区合并成一个要素做覆盖范围分析时常用。3.3 调试 PyQGIS 脚本的实用手段PyQGIS 脚本出错时报错信息经常只给一行Execution failed没有堆栈。这时候有几个手段可以定位问题。第一用QgsMessageLog把关键步骤的日志打到 QGIS 日志面板里第二在脚本里包一层try/except把完整 traceback 打出来第三如果是在 QGIS 桌面里跑脚本打开 Python 控制台看实时输出。import traceback from qgis.core import QgsMessageLog, Qgis def safe_run(func): 包装函数捕获异常并输出完整堆栈 try: return func() except Exception: # 把完整 traceback 写到 QGIS 日志和标准错误 QgsMessageLog.logMessage( traceback.format_exc(), MyPlugin, Qgis.Critical) traceback.print_exc() raise # 使用方式 safe_run(lambda: processing.run(native:buffer, {...}))QgsMessageLog.logMessage的第三个参数是日志级别Qgis.Critical会在日志面板里标红方便你快速定位。traceback.format_exc()拿到的是完整调用链比单纯print(e)有用得多。如果脚本是在 QGIS 外部跑的比如用python-qgis.bat起的独立进程traceback.print_exc()会输出到终端配合QGIS_DEBUG1的环境变量能看到 QGIS 内部的调试信息。4. 避坑与排查qgis debug 路上最常见的五个翻车点4.1 启动就崩提示找不到 qgis_core.dll现象编译通过双击 exe 或运行脚本时弹窗报错说找不到qgis_core.dll或某个 GDAL 的 DLL。原因运行时PATH里没有开发包的bin目录或者系统里装了另一个版本的 QGISDLL 被抢先加载了。解决在启动脚本里把开发包的bin目录放在PATH最前面确保优先加载。用where qgis_core.dll确认实际加载的是哪个路径下的文件。4.2 initQgis 卡住或返回后 providerList 为空现象程序在initQgis()处卡住几秒然后继续但providerList()返回空列表。原因QGIS_PREFIX_PATH没设或设错QGIS 找不到plugins目录下的数据提供者 DLL。解决确认QGIS_PREFIX_PATH指向开发包根目录且该目录下bin/plugins存在。用QgsApplication::showSettings()打印当前所有路径配置一眼就能看出哪个路径不对。4.3 调试时断点不生效调用栈全是地址现象在 IDE 里下了断点但程序跑过去不停或者停下来后调用栈显示的是十六进制地址而不是函数名。原因开发包里的 DLL 是 Release 编译的没有对应的 pdb 符号文件或者 pdb 版本和 DLL 不匹配。解决确认bin目录下有.pdb文件且和 DLL 是同一时间编译的。在 Visual Studio 里检查「模块」窗口看 QGIS 的 DLL 是否加载了符号。如果包本身不带 pdb那qgis debug就只能做到 API 层面的日志调试进不了源码。4.4 坐标系识别错误加载数据后位置偏移现象矢量数据加载后能显示但位置明显不对或者layer.crs().authid()返回空字符串。原因GDAL_DATA或PROJ_LIB环境变量没设QGIS 找不到srs.db和proj.db无法完成坐标系定义和转换。解决把这两个变量指向开发包的share/gdal和share/proj目录。如果数据本身没有坐标系信息用layer.setCrs()手动指定。4.5 Processing 算法报 Algorithm not found现象processing.run(native:buffer, ...)抛出异常提示找不到算法。原因3.6.1 里 Processing 框架需要手动初始化Processing.initialize()和addProvider(QgsNativeAlgorithms())缺一不可。解决在调用任何processing.run之前确保这两行都执行了。另外检查算法名是否正确3.6.1 的 native 算法名和后续版本有差异用processing.algorithmHelp(native:buffer)查参数定义。5. 进阶技巧把二次开发包用出生产级稳定性5.1 用 QgsTask 做后台处理避免界面卡死如果你在做桌面端二次开发任何超过 200 毫秒的操作都不应该放在主线程里。QGIS 提供了QgsTask框架把耗时任务丢到后台线程主界面保持响应。这个在 3.6.1 里已经比较成熟但用法和后续版本略有不同。from qgis.core import QgsTask, QgsApplication class BufferTask(QgsTask): def __init__(self, description, input_path, output_path): super().__init__(description, QgsTask.CanCancel) self.input_path input_path self.output_path output_path def run(self): # 这里在后台线程执行不能碰 UI 组件 layer QgsVectorLayer(self.input_path, temp, ogr) if not layer.isValid(): return False result processing.run(native:buffer, { INPUT: layer, DISTANCE: 100, OUTPUT: self.output_path }) return True def finished(self, result): # 回到主线程可以安全更新 UI if result: print(f任务完成: {self.output_path}) else: print(任务失败) # 提交任务到任务管理器 task BufferTask(缓冲区分析, D:/data/roads.shp, D:/data/out.shp) QgsApplication.taskManager().addTask(task)QgsTask的run()方法在后台线程执行里面绝对不能操作 UI 或调用QgsMessageLog之外的界面组件。finished()回到主线程适合做结果通知和界面刷新。CanCancel标志允许用户取消任务你需要在run()里定期检查self.isCanceled()并提前返回。这个模式在生产环境里是标配不用的话数据量一大界面就假死用户体验直接归零。5.2 用日志和异常兜底保证长时间运行不崩二次开发工具经常要跑批处理一跑就是几小时。这种场景下任何未捕获的异常都会导致整个进程退出前面的工作全白费。我的习惯是在任务级别做异常兜底把失败的任务记录下来继续跑下一个而不是让整个批次挂掉。import logging import traceback # 配置日志同时输出到文件和终端 logging.basicConfig( levellogging.INFO, format%(asctime)s [%(levelname)s] %(message)s, handlers[ logging.FileHandler(qgis_batch.log, encodingutf-8), logging.StreamHandler() ] ) def process_batch(file_list): 批量处理单个失败不影响整体 success, failed 0, 0 for f in file_list: try: layer QgsVectorLayer(f, temp, ogr) if not layer.isValid(): raise ValueError(f图层无效: {f}) # ... 具体处理逻辑 success 1 logging.info(f处理成功: {f}) except Exception: failed 1 logging.error(f处理失败: {f}\n{traceback.format_exc()}) logging.info(f批次完成: 成功 {success}, 失败 {failed})logging.FileHandler的encodingutf-8在 Windows 上很关键不设的话中文路径会乱码。traceback.format_exc()把完整堆栈写进日志事后排查有据可查。这个模式看起来简单但我在实际项目里见过太多人图省事不写异常处理结果跑了一夜的数据因为一个文件路径带空格就全废了。从那以后我每次写批处理都强制走一遍异常兜底和日志落盘宁可多写十行代码也不吃这种后悔药。5.3 验证开发包是否真正可用的三个检查点拿到一个二次开发包别急着写业务代码先花十分钟做三个验证。第一跑通最小初始化程序确认providerList()非空第二加载一个带坐标系的 shapefile确认crs().authid()返回正确的 EPSG 码第三跑一个 Processing 算法确认输出文件存在且要素数量合理。这三个检查点过了说明核心链路是通的后面遇到问题大概率是业务逻辑层面的而不是环境层面的。检查点验证命令/代码预期结果数据提供者QgsProviderRegistry.instance().providerList()包含 ogr、gdal、postgres 等坐标系layer.crs().authid()返回如 EPSG:4326Processingprocessing.run(native:buffer, ...)输出文件存在且可加载如果这三个检查点里有任何一个不过先别往下走回去查环境变量和依赖路径。环境问题越早暴露越好解决等到业务代码写了一堆再发现底层不通排查成本翻倍。希望帮到你。本文还有配套的精品资源点击获取
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

宁德时代AON测评|保姆级通关攻略干货✨ 2026/9/29 21:52:30

宁德时代AON测评|保姆级通关攻略干货✨

收到宁王测评邮件的宝子千万不要摆烂❗测评结果会影响后续面试,时间超级紧张,一定要认真对待! ⏰基础须知 收到测评邮件起72小时内必须完成,超时链接直接失效!优先用电脑Chrome浏览器,准备好草稿纸和计算器…

阅读更多 →
Word文档太大怎么拆分?段落结构与两种拆法的边界实测 2026/9/29 21:52:30

Word文档太大怎么拆分?段落结构与两种拆法的边界实测

上周要把自己写的一份代码应用安全评估初查报告发给三个不同的对接人,每个人只负责其中一部分。全文 2.12 MB,直接整份发过去,对方还得自己翻到对应章节。最直接的想法是把它拆开——但 Word 文档的"拆分"并不像切文本文件那么直接…

阅读更多 →
大模型应用开发岗月薪35-50K! 2026/9/29 21:52:30

大模型应用开发岗月薪35-50K!

新东方网2026年4月报道显示,AI应用开发工程师应届生校招月薪20-35K(年薪24-42W),1-3年经验月薪30-50K(年薪36-60W),资深工程师年薪60-100W。 与此同时,据新京报等媒体报道&#xff0…

阅读更多 →
变电站局放巡检用什么设备?几类检测手段的适用条件 2026/9/29 21:52:30

变电站局放巡检用什么设备?几类检测手段的适用条件

变电站局放巡检带什么设备,取决于放电点在哪、信号从哪条路径传出来。设备类型不同,外泄的信号形式不同,对应的手段也不同。局放信号往哪走,决定用哪类设备局部放电是绝缘内部或表面局部区域的反复击穿,它会产生几样东…

阅读更多 →
电子合同大批量怎么测?并发与批量处理维度专项测评 2026/9/29 21:52:30

电子合同大批量怎么测?并发与批量处理维度专项测评

旺季第一天,运营一次性发两千份合同。系统转了十分钟没动静,等页面刷出来的时候显示只发出去三百份,剩下的一千七百份状态不明,谁也不知道哪些发了哪些没发。批量和并发能力,平时完全看不出来,只在两个时刻…

阅读更多 →
ZYNQ7020从零到Linux最小系统完整实战指南 2026/9/29 21:52:23

ZYNQ7020从零到Linux最小系统完整实战指南

最近在折腾ZYNQ7020,从一片空白到最后把Linux跑起来,整个过程踩了不少坑。网上关于ZYNQ的资料虽然多,但大多是零散的知识点,真正能照着从零走到系统启动的完整流程其实不多。这篇博文就是想把我的实操过程完整记录下来——用Vivad…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉