简介:面向需要在Qt工程中接入科学计算能力的C++开发者与学习者,这套GSL部署资料围绕其环境搭建与工程集成展开,重点解决头文件引用、库文件链接和qmake配置等常见门槛。压缩包共220个文件,约328KB,其中214个h头文件覆盖GSL各数学模块的接口声明,另有2个lib库文件、pro示例工程、pri模块配置及cpp/txt说明,便于按现有工程结构快速并入。已有1898人学习下载,说明该部署方式在Qt与GSL结合场景中具有较高参考价值。读者可获得一套已整理好的库文件、头文件与pri引入配置,减少自行编译和反复排查链接错误的时间,并能借助示例工程理解qmake工程中调用GSL的组织方式。内容适合数值计算、算法验证、科研原型等开发需求,也便于初学者按目录层级对照查找所需模块。
1. 从一次链接报错说起:GSL 数学库 Qt 环境下卡在哪一步
前阵子帮人处理一个 Qt 上位机项目,里面要做传感器数据的线性拟合和统计,手写的最小二乘在数据量一大的时候结果开始飘,就换成了 GSL 数学库。改代码十分钟,#include <gsl/gsl_fit.h>编译通过,一到链接阶段,终端上冒出来一屏undefined reference to 'gsl_fit_linear',又花了将近一个下午才找到原因。
GSL 在 Qt 工程里的环境搭建,麻烦的地方向来不在代码,而在“装什么版本、库文件在哪、链接顺序怎么排、运行的时候 DLL 由谁带”。这套组合在仪器上位机、信号处理、图像算法验证里都很常见,适合手上已经有 Qt 工程、需要稳定的数值计算和统计例程的 C++ 开发者。下面按我实际的落地顺序,把 Qt 5.15 和 Qt 6 各自怎么搭配、GSL 2.7.1 和 2.8 有什么差异、装坏了怎么救,一条条走一遍。
2. 版本先定死:GSL 2.7.1 与 Qt 5.15、Qt 6 的搭配清单
装环境最容易犯的错,是先动手装,装完才发现库的文件名和 Qt 的编译器对不上。GSL 是纯 C 库,本身对编译器不算挑,但它编出来的库文件格式跟着编译器走,而 Qt 的 MinGW 套件又是每个小版本固定绑一个 GCC。三件事得一起定:Qt 版本、编译器阵营、GSL 版本。
2.1 GSL 版本决定库文件名,别到部署时才发现
GSL 2.7.1 和 2.8 功能上都能满足绝大多数场景,主要差异有两处。一处是动态库的 SONAME 变了:2.7.x 系列是libgsl.so.25,Windows 下对应libgsl-25.dll;2.8 升到了libgsl.so.27,对应libgsl-27.dll。如果部署脚本里写死了 DLL 名字,或者打包工具里配了白名单,升级 GSL 之后程序就会在客户机器上直接起不来。
另一处是构建系统。GSL 官方主推 autotools,源码包里的configure是现成的,直接跑就行;CMakeLists 属于附带支持,在 GSL 2.7.1 里还比较简陋。如果你的 CMake 版本比较新(比如 4.x),直接用源码里的 CMakeLists 构建,可能一上来就报cmake_minimum_required相关的最小版本策略错误,这个坑放到第 5 章细说。
我一般的取舍是:新工程直接上 GSL 2.8,库名新、修了不少边界问题;维护老工程、或者团队里已经有一份 2.7.1 的构建脚本在跑,就别动,版本一致性比追新重要。
| Qt 版本 | 自带 MinGW | 推荐 GSL | Windows 库文件名 |
|---|---|---|---|
| Qt 5.15.2 | MinGW 8.1.0 64-bit | 2.7.1 | libgsl-25.dll、libgslcblas-0.dll |
| Qt 6.5 / 6.6 | MinGW 11.2.0 64-bit | 2.7.1 | libgsl-25.dll、libgslcblas-0.dll |
| Qt 6.8 | MinGW 13.1.0 64-bit | 2.8 | libgsl-27.dll、libgslcblas-0.dll |
| Qt 5.15 / 6.x + MSVC 2019/2022 | 无(用 MSVC) | 2.7.1 或 2.8 | gsl.dll、gslcblas.dll |
表里这一列“自带 MinGW”不是让你去对照 MSYS2 的版本,而是提醒一件事:用哪套 Qt,就用那套 Qt 自带的 gcc 去编 GSL,别拿别处的二进制直接塞进来。
2.2 编译器阵营:MinGW 还是 MSVC
两条路都能走通,代价不一样。
MinGW 的好处是 Qt Creator 装完就有套件,调试器、make、gcc 一整套齐活,不用另外装 Visual Studio Build Tools。缺点是第三方库生态弱,vcpkg 里默认给的是 MSVC 的二进制包,想用现成的 MinGW 版 GSL,基本只能靠自己编,或者从 MSYS2 的仓库拿。
MSVC 的好处是 vcpkg 一条命令就能把 GSL 装好,头文件、lib、dll 全齐。麻烦在于 debug 和 release 的库文件不通用,.lib还分静态导入库和动态导入库,工程切构建配置的时候容易漏改路径。另外 MSVC 生成的.lib不能喂给 MinGW,反过来也一样,这个后面当踩坑单独讲。
做数值计算类的项目,我的习惯是 MinGW + 静态库。理由很实在:纯 C 的静态库libgsl.a里没有 C++ 符号,跨 GCC 小版本的 ABI 风险基本为零,链接进 exe 之后不用再操心任何 DLL 部署。代价是 exe 体积会大几百 KB 到 1MB 左右,对桌面程序不算事。
2.3 落地目录:别把第三方库塞进 Qt 安装目录
目录规划这步很多人跳过,后面换 Qt 版本的时候会一起吃一次苦头。我的固定结构是这样:
D:/sdk/ gsl-2.7.1/ include/ gsl/ gsl_fit.h gsl_statistics.h ... lib/ libgsl.a libgslcblas.a bin/ # 动态库路线时才有 libgsl-25.dll libgslcblas-0.dll三条硬性要求:路径不带空格、不带中文、不放在 Qt 安装目录下面。前两条是因为 autotools 的--prefix和 Windows 的copy命令在带空格路径上都很容易出问题;第三条是因为 Qt 升级或重装的时候会把安装目录整个覆盖掉,第三方库一起没。
工程里可以用相对路径引用,也可以写绝对路径。团队协作的项目我更倾向把D:/sdk/gsl-2.7.1换成工程根目录下的third_party/gsl,然后.pro里用$$PWD拼相对路径,这样仓库一 clone 就能编。
3. 装 GSL:三条安装路径的完整命令
GSL 在 Windows 上没有官方预编译包,这是它比 OpenCV 这类库麻烦的地方。三条路各有适用场景:Linux 开发者走包管理器,Windows 想快点看到结果走 MSYS2 预编译包,要跟 Qt 自带编译器严格对齐就走源码编译。
3.1 Linux 下用包管理器,两行命令
Debian 系和 RedHat 系的包名不一样,命令如下:
# Debian / Ubuntu 系 sudo apt-get update sudo apt-get install -y libgsl-dev # RedHat / CentOS / Fedora 系 sudo dnf install -y gsl-devellibgsl-dev会同时装上头文件和开发用的符号链接,头文件落到/usr/include/gsl/,库文件落到/usr/lib/x86_64-linux-gnu/下面,包含libgsl.so、libgslcblas.so以及带版本号的实际文件。
装完之后不需要再改任何环境变量,qmake 的-lgsl能直接找到。唯一的注意点是:如果你同时装了多个 GSL 版本(比如自己又编了一份到/usr/local),链接器会优先用/usr/local/lib下的那份,排查问题时先用ldconfig -p | grep gsl确认到底链的是哪个。
3.2 Windows 用 MSYS2 预编译包,快但版本被锁
MSYS2 的 mingw64 仓库里有现成的 GSL,一条命令:
# 在 MSYS2 的 MINGW64 shell 里执行 pacman -S --needed mingw-w64-x86_64-gsl装完头文件在/mingw64/include/gsl/,库在/mingw64/lib/libgsl.dll.a,运行库在/mingw64/bin/libgsl-25.dll。MSYS2 是一个独立的工具链,Qt 安装向导不会碰它,装好之后调用路径是C:/msys64/mingw64。
关键点:这套二进制是用 MSYS2 当前版本的 GCC 编出来的,和 Qt 5.15.2 自带的 GCC 8.1.0 不是一回事。因为 GSL 是纯 C 库,多数情况下把libgsl.dll.a喂给 Qt 的 MinGW 8.1.0 能顺利链接通过,跑起来也正常。但只要你程序里同时用到了 C++ 标准库的较新特性,运行期就可能出现libstdc++-6.dll版本打架,表现为程序启动即崩,或者在某些函数上行为诡异。
所以这条路的定位很清楚:适合快速验证接口、写 demo、确认 GSL 的 API 是不是你要的。真要发版,我建议还是用 3.3 的源码编译走一遍。
3.3 用 Qt 自带 MinGW 从源码编静态库,最稳
先把 GSL 源码包下下来,解压到一个不带空格的路径。源码包里的configure是打好的,不需要额外跑 autogen。
编译要在 MSYS2 的 MSYS shell(注意不是 MINGW64 shell)里做,因为configure是 shell 脚本,需要 sh 环境;但编译器要显式指向 Qt 自带的那套 gcc,这样才能跟 Qt 工程对齐:
# 进入解压后的源码目录 cd /d/build/gsl-2.7.1 # 创建一个独立构建目录,避免污染源码 mkdir -p build && cd build # CC 用绝对路径指向 Qt 自带的 gcc,PATH 里加上它对应的 binutils export PATH="/d/Qt/Tools/mingw810_64/bin:$PATH" ../configure \ --prefix=/d/sdk/gsl-2.7.1 \ --disable-shared \ --enable-static \ CC=/d/Qt/Tools/mingw810_64/bin/gcc.exe \ CFLAGS="-O2 -g0" make -j8 make install逐项说明这几个参数为什么这么写:
--prefix是安装目录,make install之后头文件会落到$prefix/include/gsl,库落到$prefix/lib。写绝对路径,别用~或者相对路径,make install阶段容易解析错。
--disable-shared --enable-static是关键组合。默认 GSL 会同时生成动态库和静态库,只留静态库的话,生成的libgsl.a和libgslcblas.a会被完整链进 exe,运行时不需要任何配套 DLL。这条路线最大的价值就在这里,省掉了第 4 章里最麻烦的部署环节。
CC显式指定是为了防止 MSYS 环境里 PATH 上混着别的 gcc,configure探测到错误的编译器,编出来的库跟 Qt 工程对不上。CFLAGS="-O2 -g0"里-g0是去掉调试符号,静态库体积能小一截,出问题要回溯的时候再换成-g。
编译过程中configure会跑一堆小测试程序,正常情况下最后会打印一份摘要,C compiler那一行显示的必须是你指定的那个 gcc 路径。如果显示的是/usr/bin/gcc之类,说明CC没生效,直接make distclean重来。
如果确实需要动态库版本(比如多个程序共用、或者要热更新),把--disable-shared --enable-static换成--enable-shared --disable-static,make install之后$prefix/bin下会多出libgsl-25.dll和libgslcblas-0.dll,这两个文件后面部署要跟着 exe 一起走。
MSVC 阵营的话,走 vcpkg 更省事:
vcpkg install gsl:x64-windows vcpkg integrate install装完 vcpkg 会打印出 include 和 lib 路径,记下来,第 4 章配置.pro的时候要用。x64-windows是动态库,x64-windows-static是静态库,选后者可以省掉 DLL 部署,但要注意运行库(/MD 还是 /MT)要和 Qt 保持一致,不然会出现重复定义。
3.4 装完先验货:文件对不上就别往下走
装完之后不要急着开 Qt Creator,先在终端里把文件确认一遍。这一步能拦掉后面一大半的链接错误。
# Linux:确认头文件和带版本号的库文件都在 ls /usr/include/gsl/gsl_fit.h ls /usr/lib/x86_64-linux-gnu/libgsl.so* # Windows 静态库路线:确认 .a 文件生成 ls /d/sdk/gsl-2.7.1/lib/libgsl.a ls /d/sdk/gsl-2.7.1/lib/libgslcblas.a # Windows 动态库路线:确认 DLL 和位数 file /d/sdk/gsl-2.7.1/bin/libgsl-25.dllfile命令的输出里如果出现PE32+,说明是 64 位;出现PE32而不是PE32+,就是 32 位,跟 64 位的 Qt 套件配不上,后面必然报错。没有file命令的话,用objdump -f看architecture那一行,i386:x86-64才是 64 位。
还有一点容易忽略:libgslcblas.a或者libgslcblas-0.dll必须存在。GSL 里有一批线性代数函数(比如 SVD、特征值分解)依赖 CBLAS 层,只装libgsl不装libgslcblas的情况在某些裁剪过的发行版包里有出现,链接阶段就会报一批cblas_*未定义。
4. 接进 Qt 工程:.pro 与 CMakeLists 的配置写法
库装好了,接下来是把路径和链接参数写进工程文件。qmake 和 CMake 两套写法逻辑一样,都是“头文件路径 + 库搜索路径 + 库名”,差别在语法和链接顺序的处理方式上。
4.1 qmake 的 .pro 配置与链接顺序
一个能用的最小配置长这样:
QT += core QT -= gui CONFIG += console c++17 CONFIG -= app_bundle # GSL 安装根目录,按自己的实际路径改 GSL_DIR = D:/sdk/gsl-2.7.1 # 头文件搜索路径,对应 #include <gsl/gsl_fit.h> INCLUDEPATH += $$GSL_DIR/include # 库搜索路径 + 库名,顺序不能反 LIBS += -L$$GSL_DIR/lib -lgsl -lgslcblasINCLUDEPATH加到include这一层就够了,因为 GSL 的头文件都在include/gsl/子目录里,代码里写#include <gsl/gsl_fit.h>正好能命中。
LIBS那一行的顺序是重点:-lgsl必须写在-lgslcblas前面。GNU 链接器解析符号是从左往右扫的,遇到-lgsl的时候发现里面引用了cblas_dgemm之类的符号,会先去后面还没处理的库里找,找到了才解析成功。反过来写,链接器扫-lgslcblas的时候还没看到-lgsl,等扫到-lgsl时前面的库已经处理完了,符号就悬空了,报出来的就是一堆undefined reference to 'cblas_*'或者undefined reference to 'gsl_*'。这个坑在第 5 章还会展开。
路径里如果实在避不开空格,用$$quote()把整段包起来:
GSL_DIR = "D:/Program Files/gsl-2.7.1" LIBS += -L$$quote($$GSL_DIR/lib) -lgsl -lgslcblasMSVC 套件下 qmake 会把-lxxx自动翻译成xxx.lib,所以上面这段配置在 MSVC 下也能直接用,不需要单独写一套。
4.2 CMake 工程怎么找到 GSL
Qt 6 的项目现在新建默认就是 CMake,配置写法如下:
cmake_minimum_required(VERSION 3.16) project(gsl_demo LANGUAGES CXX) set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) find_package(Qt6 REQUIRED COMPONENTS Core) # 非系统路径安装时,先告诉 FindGSL 去哪找 set(GSL_ROOT_DIR "D:/sdk/gsl-2.7.1") find_package(GSL REQUIRED) add_executable(gsl_demo main.cpp) target_include_directories(gsl_demo PRIVATE ${GSL_INCLUDE_DIRS}) target_link_libraries(gsl_demo PRIVATE Qt6::Core ${GSL_LIBRARIES})find_package(GSL REQUIRED)走的是 CMake 自带的FindGSL模块,它会去GSL_ROOT_DIR指定的目录下找头文件和库。Linux 上一般不用设这个变量,系统路径下直接就能找到。
GSL_LIBRARIES这个变量里已经按正确顺序包含了gsl和gslcblas,所以直接整个塞进target_link_libraries就行,不需要自己拆开排顺序。这是 CMake 相对 qmake 省心的一点。
如果find_package报找不到,先看 CMake 输出的GSL_INCLUDE_DIR和GSL_LIBRARY两个缓存变量被设成了什么,通常是指到了 32 位目录,或者指到了源码目录而不是安装目录。
4.3 头文件怎么包,C 头在 C++ 里的正确写法
GSL 是 C 库,头文件里有extern "C"的宏保护,所以在 C++ 里直接 include 就行:
// 直接 include,不需要手动写 extern "C" #include <gsl/gsl_fit.h> #include <gsl/gsl_statistics.h>很多人习惯性地写成这样:
// 错误示范:把 GSL 头文件包进命名空间 namespace math { #include <gsl/gsl_fit.h> }这么写会直接编译失败,或者更糟,编译通过但链接阶段报一堆找不到的符号。原因是extern "C"的作用是让 C++ 编译器按 C 的规则生成符号名(不加命名空间修饰),一旦外面又套了一层namespace,符号名就被污染了,库里的gsl_fit_linear对不上。
另一个相关的问题:不要在 GSL 头文件之后再写#define去改 GSL 的内部宏,比如GSL_RANGE_CHECK_OFF这类。这个宏必须在第一次 include 任何 GSL 头文件之前定义才有效,写在后面会产生头文件被包含两次、宏状态不一致的情况,行为很玄学。
4.4 运行期把库带上:静态库和动态库两条路
静态库路线(3.3 节里--disable-shared那条)到这里就结束了,链接完直接跑,不需要额外操作。
动态库路线要在运行期解决“exe 去哪找 DLL”的问题。Windows 上的顺序是:exe 所在目录 → 系统目录 → PATH。所以最省事的做法就是把 DLL 拷到 exe 旁边:
# 编完之后手动拷一次,或者写进构建脚本 cp /d/sdk/gsl-2.7.1/bin/libgsl-25.dll build/release/ cp /d/sdk/gsl-2.7.1/bin/libgslcblas-0.dll build/release/windeployqt只处理 Qt 自己的库,不会自动带上 GSL 的 DLL,这点要注意,打包脚本里得单独加一步。
想自动化的话,.pro里可以用QMAKE_POST_LINK挂一条拷贝命令:
win32 { GSL_BIN = $$GSL_DIR/bin OUT_BIN = $$OUT_PWD/$$DESTDIR QMAKE_POST_LINK += $$quote(cmd /c copy /y "$$shell_path($$GSL_BIN)\*.dll" "$$shell_path($$OUT_BIN)") $$escape_expand(\\n\\t) }这里有个细节:路径末尾如果带反斜杠,Windows 命令行会把紧接着的引号当成转义符吃掉,命令直接报语法错误。所以OUT_BIN拼出来之后不能以\结尾,$$DESTDIR为空的时候$$OUT_PWD/就是这种情况,稳妥的做法是给DESTDIR显式赋一个子目录名。
Linux 上动态库不在系统路径时,用 RPATH 把查找路径写进可执行文件:
unix:!macx { QMAKE_RPATHDIR += $$GSL_DIR/lib }QMAKE_RPATHDIR会被翻译成-Wl,-rpath,<路径>,程序启动时就能找到库,不需要去改LD_LIBRARY_PATH,也不需要ldconfig。
5. 避坑与排查:五类翻车现场的现象、原因和救法
下面这几条都是我或者身边的人实际撞过的,按从编译期到运行期的顺序排。
5.1 编译与链接阶段:符号找不到、格式对不上
第一条,undefined reference to 'gsl_fit_linear',头文件能过,链接全红。
现象:编译阶段一点问题没有,链接阶段刷出一屏未定义符号,全是gsl_*或者cblas_*。
原因:九成是链接顺序写反了,-lgslcblas写在-lgsl前面,或者干脆只写了-lgsl漏了-lgslcblas。剩下的一成是-L路径写错,链接器在指定目录里没找到库文件,但它不报“找不到库”,只报符号未定义,误导性很强。
解决:先按 4.1 的顺序改成-lgsl -lgslcblas。还不行就确认-L指向的目录里真的有libgsl.a或libgsl.dll.a,用ls看一眼比猜快得多。确认库文件存在的话,用nm看符号有没有导出来:nm -g libgsl.a | grep gsl_fit_linear,有输出说明库本身没问题,问题一定在链接参数上。
第二条,cannot find -lgsl或者 MSVC 下的LNK2019。
现象:MinGW 报cannot find -lgsl,MSVC 报LNK2019: 无法解析的外部符号 _gsl_fit_linear。
原因:两种可能。一是编译器阵营和库格式不匹配,拿 MSVC 编的.lib喂给 MinGW,或者反过来,两边都认不出对方的格式。二是位数不匹配,64 位工程链接了 32 位的库,报错信息有时候很含糊,只说是“格式无效”。
解决:先确认 Qt 套件是哪个编译器,再确认库是哪个编译器编的,两边必须一致。位数用 3.4 节的file或objdump -f看,PE32+对 64 位。MSVC 下还要注意 debug 和 release 不能混用,gsl.lib和gsld.lib是两个不同的文件,工程切配置的时候路径要跟着换。
第三条,CMake 4 下构建 GSL 源码,一上来就报策略错误。
现象:执行cmake ..立刻失败,提示Compatibility with CMake < 3.5 has been removed。
原因:GSL 2.7.1 源码里附带的 CMakeLists 写的是cmake_minimum_required(VERSION 2.8.12)这个级别,CMake 4.0 开始彻底移除了对 3.5 以下版本的兼容,老工程一律拒绝配置。
解决:加一个变量绕过,cmake -DCMAKE_POLICY_VERSION_MINIMUM=3.5 ..。但这只是让它能跑起来,GSL 的 CMake 支持本身在 2.7.x 里就不完整,少了一些 install 规则。稳妥的做法是老老实实用 autotools,走 3.3 节那套configure && make && make install,别跟 CMake 较劲。
5.2 运行与工程配置阶段:DLL 找不到、配置不生效
第四条,Qt Creator 里能跑,双击 exe 就崩。
现象:在 IDE 里按 F5 一切正常,切到构建目录里双击 exe,弹窗提示缺少libgsl-25.dll,或者直接以0xc000007b退出。
原因:Qt Creator 启动程序的时候会把 Qt 的 bin 目录和工具链目录加进 PATH,所以 DLL 能被找到;双击运行没有这个 PATH,就只能靠 exe 同目录。0xc000007b更具体一点,通常是位数不匹配——拷了个 32 位的 DLL 到 64 位程序的目录里。
解决:把libgsl-25.dll和libgslcblas-0.dll拷到 exe 同目录,位数用objdump -f核一遍。另外提一句,如果同时装了多个版本的 GSL,PATH 里可能混着老版本,libgsl-25.dll和libgsl-27.dll同时存在一个目录里,程序加载哪个取决于链接时记录的名字,容易出玄学问题,所以目录结构还是按 2.3 节那样一个版本一个目录最省心。
第五条,改了.pro没生效,报错还是老一套。
现象:明明已经把LIBS改对了,重新构建还是报同样的链接错误,甚至报的路径是修改之前的。
原因:qmake 生成的 Makefile 是缓存下来的,只按 Ctrl+B 构建不会重新跑 qmake,Makefile 里还是旧参数。构建目录里残留的.o文件也会让某些改动看起来“没生效”。
解决:Qt Creator 里先执行“执行 qmake”,再“重新构建”;命令行的话是qmake然后make clean && make。还不行就把构建目录整个删掉重来一次,比一点点排查快。从这以后我养成一个习惯:凡是动过.pro或CMakeLists.txt,第一步永远是清构建缓存,不给自己留悬念。
6. 验证跑通:一个能算出数的最小例程
配置对不对,光看编译过没过不够,得让它真算出一个结果。下面这个控制台程序用 GSL 做一次一元线性拟合,同时调一个统计函数,把两个不同头文件的符号都走一遍。
#include <QCoreApplication> #include <QDebug> #include <gsl/gsl_fit.h> #include <gsl/gsl_statistics.h> int main(int argc, char *argv[]) { QCoreApplication app(argc, argv); // 构造一组带微小扰动的线性数据 y = 2x + 1 const double x[] = {0.0, 1.0, 2.0, 3.0, 4.0, 5.0}; const double y[] = {1.02, 2.98, 5.05, 6.97, 9.03, 11.01}; const size_t n = sizeof(x) / sizeof(x[0]); double c0 = 0.0; // 截距 double c1 = 0.0; // 斜率 double cov00 = 0.0, cov01 = 0.0, cov11 = 0.0, sumsq = 0.0; // stride 传 1 表示数组元素连续存放,不是间隔 1 字节 const int rc = gsl_fit_linear(x, 1, y, 1, n, &c0, &c1, &cov00, &cov01, &cov11, &sumsq); if (rc != GSL_SUCCESS) { qWarning() << "gsl_fit_linear failed, code =" << rc; return 1; } qDebug().noquote() << QStringLiteral("拟合结果: y = %1 * x + %2") .arg(c1, 0, 'f', 6).arg(c0, 0, 'f', 6); qDebug().noquote() << QStringLiteral("残差平方和: %1").arg(sumsq, 0, 'f', 6); // 再调一个统计函数,确认第二个头文件的符号也能链上 const double mean = gsl_stats_mean(y, 1, n); qDebug().noquote() << QStringLiteral("均值: %1").arg(mean, 0, 'f', 6); return 0; }`gsl_fit
本文还有配套的精品资源,点击获取