尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

QtCreator集成CCCoreLib:MSVC编译配置与点云算法库接入全流程

QtCreator集成CCCoreLib:MSVC编译配置与点云算法库接入全流程 简介CCCoreLib是CloudCompare的核心算法库面向三维点云处理开发者与研究者。这份资源提供VS2019编译器生成的完整源码、lib静态库与dll动态库可直接导入QtCreator工程使用免去自行编译与依赖配置的繁琐过程。包体包含102个文件其中63个头文件与34个cpp源文件覆盖点云读取、几何分析、配准、分割等核心模块另附1个lib、1个dll和1个hpp整体仅567KB轻量且结构清晰。已有492人学习下载。借助该资源可快速调用ccLoadCloud、ccCompareClouds等API在Qt环境中实现点云处理、算法修改与功能扩展适合希望深入CloudCompare开发或学习其核心实现的开发者。 说实话点云处理这个圈子绕不开 CloudCompare而 CCCoreLib 就是它背后那个真正干活的算法内核。遇到过的情况大概是这样的自己写 Qt 桌面程序要集成点云滤波、法线估计、ICP 配准这些功能不想从零造轮子于是拉了一份 CCCoreLib 源码准备在 Windows 上编出 lib/dll 给工程用。结果一堆人卡在“源码有了VS2019 也装了QtCreator 就是死活链接不上各种 LNK 报错”。这篇文章就把我从拿到源码到在 QtCreator 里跑通全流程捋一遍涉及到 VS2019 编译器选型、CMake 生成工程、lib/dll 的生成和调用以及几个典型的坑给后面做点云应用开发的人一个可以直接抄的作业。1. 项目背景与整体思路1.1 CCCoreLib 是什么为什么要在 QtCreator 里用CCCoreLib 是 CloudCompare 的算法核心库里面封装了大量点云和网格处理的基础算法比如八叉树建树、最近邻搜索、法线估计、ICP 配准、泊松重建、栅格降采样、连通分量分割这些。说得直白一点CloudCompare 软件本身只是一个壳子真正的计算逻辑基本都抽到了这个库里。对做工业测量、三维扫描后处理、机器人感知相关项目的人来说直接在自有 Qt 工程里复用这套算法是非常诱人的一件事一是算法经过 CloudCompare 多年验证稳定性有保障二是不用自己研究怎么把几十个源文件组织成工程省掉很多基础设施时间。但问题也跟着来了——CCCoreLib 官方在 Windows 下的推荐编译方式是 MSVC也就是 VS2019而很多桌面开发者的日常 IDE 是 QtCreator两者要配合就必须经过一层“先编译库、再接入工程”的处理。在动手之前需要明确一件事QtCreator 只是个 IDE真正编译代码的是编译器。QtCreator 下常见的编译器有 MinGW GCC 和 Microsoft Visual CMSVC 两种。VC的lib/dll跟MinGW的a/dll不是一套ABI直接混用几乎必炸。所以我们整个方案的起点就是用 VS2019 编译源码产出 dll/lib再让 QtCreator 切换到 MSVC 工具链去消费这两个文件。1.2 编译方案选型为什么选 VS2019 CMakeCCCoreLib 的仓库是标准的 CMake 工程没有强行绑定 Qt纯 C 算法库依赖相对可控。选 VS2019 作为编译器有几点考虑一是官方 Windows 构建脚本和 CI 用的就是 MSVC出问题能少踩一半坑二是 QtCreator 从 4.x 开始对 MSVC 套件支持得已经很成熟完全可以在 QtCreator 里写代码、用 MSVC 编译逻辑上并不矛盾。另一个方案是直接用 QtCreator 打开源码里的 CMakeLists.txt让 QtCreator 自动配置生成工程这确实也能做但有几个麻烦点QtCreator 默认会把 CMake 生成的构建目录结构弄得比较“个性”而且如果装的是新版本 CMakeQtCreator 内部的 CMake 版本也可能跟 VS2019 的生成器存在兼容问题。我的建议是更传统但更可控的两段式先用 CMake 命令行生成 VS2019 解决方案在 VS2019 里点两下编译生成 dll/lib再去 QtCreator 里通过 .pro 文件把库链进自己的应用工程。这样每一步产物是清楚的出了问题也容易定位。2. 环境准备与源码获取2.1 开发环境清单与版本匹配这个环节看着基础但不少人恰恰是这里没到位导致后面连环报错。整套环境的版本组合我用的是经过验证的组件版本建议说明操作系统Windows 10/11 64位32位环境建议直接放弃点云数据量上去后内存根本不够VS2019Community 16.11 及以上务必安装“使用 C 的桌面开发”工作负载CMake3.20 以上VS2019 对应的 MSVC 生成器需要 CMake 3.14 才支持完整特性Qt5.15 或 6.2QtCreator 建议安装“MSVC 2019 64bit”构建套件Git任意较新版本拉取源码用有两点我要特别强调。第一VS2019 安装时一定要把 Windows 10 SDK 勾上否则 QtCreator 里的 MSVC 工具链会因为缺少 SDK 而无法识别。我见过有人 VS 装完只选了 C 编译核心结果 QtCreator 里能看到编译器却无法构建排查了半天才发现是 SDK 缺失。第二如果机器上同时装了 VS2019 和 VS2022QtCreator 会自动检测到多个 MSVC 版本选择套件时务必看清楚Kit 名称里会直接标识 “MSVC2019 64bit” 还是 “MSVC2022 64bit”选错的话链接阶段符号版本不一致报错会非常诡异。2.2 获取源码与目录结构梳理源码直接从 GitHub 仓库拉取参照 CloudCompare 官方仓库中的 CCCoreLib 子项目。整体目录结构大概是这样的CCCoreLib/ ├── include/ │ ├── CCCoreLib.h │ ├── CCCoreLibConfig.h │ ├── DgmOctree.h │ ├── PointCloudTpl.h │ ├── ... ├── src/ │ ├── DgmOctree.cpp │ ├── PointCloudTpl.cpp │ ├── ... ├── plugins/ ├── CMakeLists.txt ├── LICENSE这个库的头文件组织比较规整公开接口基本都集中在 include 目录源码在 src 目录。它依赖的第三方库很少核心部分基本不需要额外下载依赖只有用到某些扩展算法时才会涉及到 Eigen 之类的外部库。所以拉完源码直接跑 CMake 就可以不需要像 OpenCV 那样先装一堆依赖。多说一句如果用 git clone 要注意分支。master 分支跟随上游开发API 变化会比较频繁。如果用稳定版本建议 checkout release 标签比如 v2.0.0 之类的版本号这样后续链接阶段不会因为接口签名变化而反复改代码。我一开始直接拉 master编译倒是过了但后来发现某个类的方法在两周后的提交里被重命名了Qt 工程里调用处全部编译失败后来老老实实切到 release 分支才消停。3. 用 VS2019 编译 CCCoreLib 生成 lib 和 dll3.1 CMake 配置生成 VS 工程打开“x64 Native Tools Command Prompt for VS2019”或者用普通 CMD 但确保 CMake 在 PATH 里。在源码根目录执行cmake -S . -B build -G Visual Studio 16 2019 -A x64这条命令指定了生成器为 VS2019架构为 x64。如果不指定 -A x64CMake 默认可能会生成 Win32 工程后面链接 x64 的 dll 时会因为位数不一致直接报错。所以位数这件事情从 CMake 生成阶段就要死死定住不要寄希望于后面再切换。生成成功后build 目录下会看到CCCoreLib.sln解决方案文件。双击打开在解决方案管理器中找到CCCoreLib项目右键“生成”。第一次编译会比较慢主要是要编译的源文件数量和模板实例化都不少大概在几十个 cpp 的规模。编译结束后在build/Release/或build/Debug/目录下能看到产物。关于 Debug 与 Release 的选择我建议同时编两个版本。Debug 版本的 DLL 和 Release 版本不能混用否则运行时会随机崩溃或者出现莫名其妙的“内存访问冲突”。不少人的 Qt 程序自己编译用的是 Debug 模式结果链接的 CCCoreLib 是 Release 库表面看没报错一运行就挂花了很多时间查业务逻辑最后发现是库配置混了。3.2 动态库与静态库的选择这里涉及一个关键选项CCCoreLib 在 CMake 中默认编译类型由BUILD_SHARED_LIBS控制。默认情况下可能是静态库可以通过 CMake 配置显式指定cmake -S . -B build_dll -G Visual Studio 16 2019 -A x64 -DBUILD_SHARED_LIBSON两种方式各有适用的场景我建议按照下面的标准来选方式产物优点缺点静态库CCCoreLib.lib体积较大部署简单exe 一个文件带走无 DLL 缺失问题编译时间长exe 体积膨胀动态库CCCoreLib.dll CCCoreLib.lib导入库更新库时只需替换 DLL多个程序可共享部署时必须带上 DLL还要处理运行路径我的做法是如果只是自己项目内部使用优先静态库省去一大堆 DLL 路径问题如果打算把库作为插件体系的一部分或者多个可执行模块都要复用同一个算法库那就上动态库。下面我按动态库方式继续讲因为工作中遇到的大多数问题场景都是 DLL 方式。3.3 输出产物与头文件配套生成动态库后实际需要保留的文件如下CCCoreLib.dll # 运行时要加载的动态库 CCCoreLib.lib # 链接时使用的导入库 include/ # 全部头文件调用方编译需要有个细节很多人会忽略include/CCCoreLibConfig.h这个文件是整个库编译导出的关键配置头。CCCoreLib 使用CC_CORE_LIB_API这类宏来控制导入导出而这个宏定义在CCCoreLibConfig.h中。如果你把这个文件漏了或者用了源码里错误的版本链接阶段会有一大堆“无法解析的外部符号”报错。所以拷贝头文件时整个 include 目录原样搬走千万别手动筛。编译完成后在 build 目录下的 CMakeCache.txt 里还埋着很多有用的路径信息比如依赖的三方库路径、安装路径等。不过对我们这种只取库文件的使用方式不需要执行cmake --install手动拷贝即可。4. 在 QtCreator 工程中接入4.1 用 .pro 组织包含路径与链接参数假设你的 Qt 工程是一个标准 qmake 管理的 Widgets 程序那么接入工作主要写在.pro文件里。我的.pro核心片段如下# 编译使用 MSVC2019 64bit 套件的前提下 CONFIG c17 INCLUDEPATH $$PWD/../CCCoreLib/include CONFIG(debug, debug|release) { LIBS -L$$PWD/../CCCoreLib/build/Debug -lCCCoreLib } else { LIBS -L$$PWD/../CCCoreLib/build/Release -lCCCoreLib } # 如果你不是用相对路径也可以用绝对路径 # LIBS -LC:/dev/libs/CCCoreLib -lCCCoreLib # Windows 下建议打开这个否则某些平台相关的 min/max 宏会干扰算法头文件 DEFINES NOMINMAX这里的-lCCCoreLib会在指定目录下查找CCCoreLib.libMSVC 工具链或libCCCoreLib.aMinGW 工具链。如果链接阶段找不到库就去检查-L指定的目录和-l的库名是否精确匹配。文件名无规则变化是 Link 报 LNK1104 的常见原因。重点解释一下NOMINMAX这个宏。Windows 的windows.h里定义了min和max宏而 CCCoreLib 的模板代码里大量使用了std::numeric_limitsT::max()这种标准写法。如果不禁用 Windows 宏编译器会把代码里的max直接替换成宏导致一大堆语法错误。这个问题在 MSVC 工具链下基本是必现的Qt 的某些模块会在全局引入 Windows 头所以提前在.pro里加 DEFINES 是最稳妥的。4.2 构建套件必须选择 MSVCQtCreator 安装后默认会带一个 MinGW 套件很多新手直接用这个套件去编译然后链 VS2019 生成的 lib结果一堆 LNK2001、LNK2019 无法解析的外部符号。原因很简单MinGW 的 C 符号修饰规则name mangling跟 MSVC 不一样两边编出来的 obj 文件根本不是一套 ABI。正确操作是在 QtCreator 菜单“工具 - 选项 - Kits”下添加或选择 MSVC2019 64bit 套件。前提是安装 VS2019 时勾选了 C 工作负载QtCreator 才能自动检测到 MSVC 工具链。套件配置要点配置项设置编译器Microsoft Visual C Compiler 16.x (x86/amd64)调试器使用 CDB 或 windows 下的 gdb建议 CDBQt 版本选择 Qt 5.15.x 或 Qt 6.x 的 MSVC 版本CMake 工具系统安装的 CMake这里要特别提醒如果你想彻底避开调试器那一堆麻烦最简单的方式是把编译器选正确然后构建、运行都用这个套件。如果你发现构建套件列表里根本没有 MSVC八成是 VS2019 安装时没有安装“使用 C 的桌面开发”工作负载回去重新修改安装即可不用重装 VS。4.3 运行时部署 DLL 与依赖检查把程序编译通过只是第一步运行时 DLL 找不到是第二大高频问题。QtCreator 直接按“运行”按钮时它会设置一个特定的 PATH但往往不包含你的 CCCoreLib.dll 所在目录。处理方式有几种从简单到规范排列把CCCoreLib.dll复制到生成的 exe 同目录下简单直接。在 QtCreator 的“运行环境”里新增 PATH 项把 DLL 所在目录加进去。在.pro中使用QMAKE_POST_LINK在每次构建完成后自动拷贝 DLL适合频繁迭代的场景。# 每次构建后自动拷贝 DLL 到目标目录 win32 { CONFIG(debug, debug|release) { QMAKE_POST_LINK $$quote(cmd /c copy /Y $$PWD/../CCCoreLib/build/Debug/CCCoreLib.dll $$OUT_PWD/debug/) } else { QMAKE_POST_LINK $$quote(cmd /c copy /Y $$PWD/../CCCoreLib/build/Release/CCCoreLib.dll $$OUT_PWD/release/) } }把这两行加进去之后每次 F5 运行都不会再出现“找不到 CCCoreLib.dll”的弹窗。此外可以用 Dependencies 这类工具检查 DLL 的依赖树确保 CCCoreLib.dll 本身没有缺少它自己的运行时组件比如 VCRUNTIME140.dll。正常情况下 VS2019 编译的 DLL 会依赖 VC 运行库目标机器如果没有安装 VC Redistributable程序同样起不来这是部署到其他电脑时重点关注的一项。5. 常见问题与排查技巧实录5.1 高频报错速查表我整理了自己实际踩过或者说身边朋友问过最多的几类问题按出现频率排序报错现象根本原因解决办法LNK1104 无法打开文件 CCCoreLib.lib库路径不对或库文件名大小写、后缀不一致检查 .pro 的 -L 路径确认生成的 lib 是 Release 还是 DebugLNK2001/LNK2019 无法解析的外部符号MinGW 与 MSVC 混用或头文件宏定义不一致统一使用 MSVC2019 构建套件确认CCCoreLibConfig.h中的导入导出宏正常生效运行时提示找不到 CCCoreLib.dllDLL 不在 exe 目录或 PATH 中将 DLL 拷贝到 exe 目录或用 QMAKE_POST_LINK 自动部署编译时报 C4996locale相关告警且无法定位MSVC 对 locale 的安全警告在 .pro 增加DEFINES _CRT_SECURE_NO_WARNINGS屏蔽Qt 程序一运行就崩溃且崩溃点在随机位置Debug 库和 Release 库混用整条工具链统一 Debug 或 Release禁止混搭程序体积异常巨大且链接奇慢可能存在大量模板实例化可以考虑改用动态库若无效则关闭 /GL 等全局优化重新链接其中最坑的其实是第一个 LNK1104。因为 QtCreator 构建时默认把构建目录放在 build-工程名-套件名-配置 这种子目录里很多人的.pro文件写的是相对路径写到$$PWD/../lib/结果发现相对于build目录不同层级导致找不到建议优先用绝对路径或者通过变量传递路径。5.2 几个“断根式”的避坑心得第一永远保持架构一致。x64 的 Qt 工程只能链接 x64 的 CCCoreLib.lib。很多人 VS 编译时没注意平台生成了 Win32 的库Qt 工程又是 x64链接阶段直接报错这种问题往往要查很久。生成 VS2019 工程时用-A x64就能从源头杜绝。第二小心源码中的中文注释。VS2019 默认对源码文件按系统 ANSI 代码页解析如果源码文件是 UTF-8 无 BOM 格式且包含中文注释MSVC 可能报 C4819 警告严重时直接编译失败。碰到时在源码根目录的 CMakeLists 里全局加编译选项或者在 VS2019 中给项目增加/utf-8编译参数。QtCreator 侧也可以在.pro里加QMAKE_CXXFLAGS /utf-8。这个坑在第三方源码仓库里尤其常见因为它们的主力维护者大概率不在中文 Windows 环境下开发文件格式不一定兼容本地编码设置。第三一定把集成测试写好再推进业务。库接进来后先写一个最小可执行样例做好 sanity check比如建一个简单的点云容器插入几千个点然后算一次八叉树半径搜索确认结果在合理范围。这一步看着简单但能一次性暴露架构、编码、链接、运行期 PATH 的所有问题省下的排查时间远大于写这几行测试的时间。我个人每次接手这种第三方库集成时的习惯是先读目标库的 CMakeLists 前 80 行确认默认构建选项再决定用静态库还是动态库然后才动手跑 CMake。这个习惯帮我避开过好几次因为默认关闭了共享库导出宏导致的链接异常。CCCoreLib 的文档不算多但官方 GitHub 的 Issues 区非常活跃遇到疑难问题先去那边搜很多时候你会发现自己遇到的问题别人三个月前就踩过了。本文还有配套的精品资源点击获取
返回列表