Clion下配置GDAL开发环境(不用编译GDAL源码)
一、写在前面
虽然之前通过
Vcpkg
配合CMake
在MinGW
的环境下成功安装了GDAL3.6.2
,但是环境存在缺陷,压根就无法读取数据,举几个例子;
下面有直接安装教程的完整步骤,移步目录第三节。
二、我遇到的问题
1、ERROR 4: xx\xx\test.gdb: Permission denied
特别让人头疼的一个问题,错误显示文件权限不够,于是我找到这个GDB文件,尝试更改他的属性为当前用户全权控制,但是我发现我当前的用户是
Administrator
,对这种普通数据文件都是拥有全部权限的,所以压根就不用改。
改变思路,用管理员模式打开
Clion
,再次运行这个程序,发现还是Permission denied
。我真服了!
又想到由于之前是用
Java
通过JNI
调用GDAL
的动态库,所以安装了其他版本的GDAL
。卸载Java
的GDAL
,再次运行,还是失败。心态彻底崩了 …
最后是在
GDAL
官网看到教程解决了问题,读取数据源GDALDataset
一开始我用:
auto *poDataset = (GDALDataset *)GDALOpen(R"(C:\test.gdb)",GA_ReadOnly);
结果这种方式死活有权限问题:
ERROR 4: C:\test.gdb: Permission denied
,改为官网用的c++读取方式后就没有出现权限问题了,经过了解我发现GDALOpen
主要用于打开栅格数据文件,而GDALOpenEx
提供了更广泛的功能,支持打开矢量和栅格数据,同时还允许指定打开模式和其他选项。
auto poDS = (GDALDataset *) GDALOpenEx(R"(C:\test.gdb)",
GDAL_OF_VECTOR, nullptr,nullptr, nullptr);
2、无法读取到图层,但是图层指针不为NULL(nullptr)
解决了权限的问题后,开心的往下写,获取数据源,通过数据源获取图层,问题随着也来了,图层获取没问题,图层指针也不为
NULL
或者nullptr
,但是如果通过图层获取要素或者图层其他相关属性的话,程序就错误退出了。贴出代码:
#include <iostream>
#include "ogrsf_frmts.h"
using namespace std;
int main() {
GDALAllRegister();
auto *poDataset = static_cast<GDALDataset*>(GDALOpenEx(
R"(C:\test.gdb)",
GDAL_OF_VECTOR,
nullptr,nullptr, nullptr));
if (poDataset == nullptr){
cout << "数据源空" << endl;
exit(-1);
}
int layer_count = poDataset->GetLayerCount();
cout << "读取到的图层数量:" << layer_count<< endl;
cout << "开始读取图层" << endl;
auto *layer = (OGRLayer *)poDataset->GetLayer(0);
if (layer == nullptr){
cout << "图层为空" << endl;
exit(-1);
}
GDALClose(poDataset);
return 0;
}
运行这个程序,发现输出了
读取到的图层数量:0
和图层为空
,我超?没道理啊,于是换成c
的读取方式:
cout << GDALDatasetGetLayerCount(poDataset) << endl; //结果:1
来了,诡异的情况出现了,这种方式居然正确的读取到了图层数量!于是继续用这种方式读取图层:
auto *layer = (OGRLayer *)GDALDatasetGetLayerByName(poDataset,"test_layer");
读取到了,并且图层指针不为
NULL
或nullptr
,尝试通过图层指针获取图层名:
cout << layer->GetName() << endl;
不出意外地意外出现了,程序错误退出了,并且控制台没有任何错误信息…
研究了好久,终于找到解决办法了:
三、通过VisualStudio
环境加CMake
编译已有程序
1、引言
上面的方式都是用的
Clion
+MinGW
+CMake
的方式编译的项目,但是不同的是,MinGW
用的动态库不是dll
,它用的是dll.a
,我通过Vcpkg
安装的GDAL
库都是dll
。当然,用MinGW
也是能用的,只是比较麻烦,要把当前用到的GDAL
库转换为dll.a
,才能用MinGW
编译整个项目,于是我换了个思路,之前用的方式一直都是:
当我把它换成
VisualStudio
环境后就成功了:
2、具体操作
好了,情况大概就是这么个情况,接下来我们从0开始具体操作,希望能帮到你;
首先各工具版本声明,下载地址我就不给了,难得找:
工具 | 版本 |
---|---|
VisualStudio | 2022-17.9.1 |
Clion | 2023.3.3 |
CMake(可选) | 3.27.9 |
Vcpkg | GitHub拉取,保持最新 |
GDAL | 3.6.0以上 |
Ⅰ、安装VisualStudio
并且添加C++
的环境,下载就行了,都是图形化操作。
Ⅱ、安装CMake
(可选),无脑下一步就行,只是要记住安装位置。
Ⅲ、安装Clion
,并且新建一个C++
可执行文件项目:
打开
设置
->构建、执行、部署
->工具链
,添加一个环境,选择VisualStudio
,记得如果有多个环境,一定要让VisualStudio
在第一个,可以通过+
右边的上下按钮调整位置:
工具集选择你的
VisualStudio
安装位置:
CMake
可以用VisualStudio
自带的,也可以用我们刚才安装的,如果用我们自己安装的,目录选择的时候到bin
下的cmake.exe
就行:
其他的都不用管。
Ⅳ、安装Vcpkg
,并且安装GDAL
这一步主要是免去编译
GDAL
源码的麻烦,Vcpkg
给我们编译好,如果你自己编译了GDAL
源码,那么可以不用Vcpkg
,安装Vcpkg
教程看我的另外一篇博客,可以根据这篇博客安装GDAL
。
此外,如果你用Vcpkg
的时候,不想用它默认安装的GDAL
版本,那么可以更改Vcpkg
的清单,也就是说你要在清单模式下才能指定版本,否则就是默认版本:
Vcpkg
初始化好了以后,默认不是清单模式,你需要选择这个{ }
才能切换清单模式,点击后会弹出一个对话框让你选择,什么都不选,确定,Vcpkg
就会在项目的根目录下生成一个vcpkg.json
文件,这个文件有点类似Java
中的Manve
的pom
文件,管理依赖的:
相信你也看到了,只需要将
dependencies
这项改成像我一样,然后下面再加一个overrides
就能指定版本了,其他的Vcpkg
设置请移步 微软Vcpkg文档:
"dependencies" : [ "gdal" ],
"overrides": [
{
"name": "gdal",
"version": "3.6.1"
}
]
修改好了以后,删掉根目录下生成的
cmake-build-debug
目录,并点击上方的工具
->CMake
->重新加载CMake项目
,耐心等待CMake执行完成:
这里比较慢,耐心等待,因为是从GitHub上下载,我开启了科学上网,耗时大概在二十分钟到四十分钟左右
CMake
执行完成后如果出现类似:
这样的字样的话,就代表安装成功了,将这两句代码放到项目根目录下的CMakeLists.txt中去:
cmake_minimum_required(VERSION 3.27)
project(gdal_test)
set(CMAKE_CXX_STANDARD 17)
find_package(GDAL CONFIG REQUIRED)
add_executable(gdal_test main.cpp)
target_link_libraries(gdal_test PRIVATE GDAL::GDAL)
注意
find_package(GDAL CONFIG REQUIRED)
要放在add_executable()
前,target_link_libraries(main PRIVATE GDAL::GDAL)
要放到add_executable()
后,并且括号内的main
要改为你的项目名字,改完后重新加载项目:
Ⅴ、配置PORJ_LIB
环境变量。
这里有一个比较坑的点,就这么安装完后,会有几率出现关于
proj
的报错,所以我们得手动配置一个proj
的环境变量以防外一。
添加环境变量
PROJ_LIB
,指向那会Vcpkg
安装目录下的
vcpkg安装目录/packages/proj_x64-windows/share/proj
如果你使用Vcpkg
成功安装了GDAL
,那么proj_x64-windows
肯定会有的,因为这是GDAL
的最大依赖,如果你没有这个文件夹,那么请反思,检查哪一步出了问题。
弄完环境变量后,写测试代码测试环境是否成功:
#include <iostream>
#include "ogrsf_frmts.h"
using namespace std;
int main() {
GDALAllRegister();
CPLSetConfigOption("GDAL_FILENAME_IS_UTF8", "YES");
//判断一下驱动
const char *driver_name = "FileGDB";
GDALDriver *poDriver = GetGDALDriverManager()->GetDriverByName(driver_name);
if (poDriver){
cout << "不存在驱动:" << driver_name << endl;
}
auto *poDataset = static_cast<GDALDataset*>(GDALOpenEx(
R"(F:\dev_file\test_file\test.gdb)",
GDAL_OF_VECTOR, nullptr,
nullptr, nullptr));
if (poDataset == nullptr){
cout << "数据源空" << endl;
exit(-1);
}
int layerC = poDataset->GetLayerCount();
cout << "读取到的图层数量:" << layerC << endl;
cout << "开始读取图层" << endl;
auto *layer = (OGRLayer *)poDataset->GetLayer(0);
if (layer == nullptr){
cout << "图层为空" << endl;
exit(-1);
}
const char *layer_name = layer->GetName();
cout << "图层名:" << layer_name << endl;
auto *feature = layer->GetFeature(1);
auto *geom = feature->GetGeometryRef();
cout << "图层读取完成" << endl;
GDALClose(poDataset);
return 0;
}
如果没有任何报错且输出正常则环境配置成功
四、总结
首先本文这么做的原理是,我们通过安装
VisualStudio
获取到VisualStudio
的编译环境,Clion
默认使用的是MinGW
编译环境,我们将它换为VisualStudio
。
此外,传统的VisualStudio
开发需要你自己编译GDAL
源码为.lib
库或者.dll
库,如果使用MinGW
编译环境也要将GDAL
编译好的.dll
、.lib
库转换为MinGW
能用的库,有点麻烦,我没操作过,可以了解一下。
再然后通过Vcpkg
安装GDAL
,就可以免去手动编译GDAL
的麻烦,开箱即用。
再贴一个官方 GDAL教程 的链接,配合科学上网使用最佳。
大概就这么多,后续有问题我会继续补充或修改这篇博客的内容,如果你遇到了本文之外的问题,可以在评论区留言,我会的尽量帮。