GDAL+HDF4+HDF5+netCDF库编译C#

来源:互联网 发布:foxit editor mac 编辑:程序博客网 时间:2024/06/05 04:24

最近读取GPM降雨数据,涉及到读取.nc文件和.hdf5文件,虽然matlab可以轻松解决问题,偏又脑子发热想结合刚开始学的C#写代码读数据于是便有了下文。
网上搜索了好久,发现GDAL库提供多种栅格数据和矢量数据的读取。于是开始学习GDAL库的使用,无奈GDAL库并不直接支持HDF文件和nc文件的读写,而需要在编译的时候添加相应的库。百度+http://www.gdal.org/+李民录的《GDAL源码剖析与开发指南》自己瞎鼓捣了几天终于搞成功了,现在记录如下。
1. 相关库文件下载地址
开发平台:Visual Studio 2012;
GDAL源码版本:2.2.2,下载地址:http://trac.osgeo.org/gdal/wiki/DownloadSource;
HDF4库文件版本:HDF4.2.6_win_x86,下载地址:https://support.hdfgroup.org/ftp/HDF/releases/HDF4.2.6/bin/windows/;
HDF5库文件版本:HDF5-1.8.7_win_x86,下载地址:https://support.hdfgroup.org/ftp/HDF5/releases/hdf5-1.8/hdf5-1.8.7/bin/windows/;
netCDF库文件版本:netCDF_4.5.0-rc3,下载地址:http://www.unidata.ucar.edu/software/netcdf/docs_rc/winbin.html;
SWIG软件版本:2.0.12,下载地址:https://sourceforge.net/projects/swig/files/swigwin/;
说明:GDAL源码和netCDF选择的是当前最新版本(注意博客日期)。HDF库我用最新版本试过,但是编译失败了,后来直接按照《GDAL源码剖析与开发指南》下载了这两个版本,最后成功了。SWIG用于向脚本语言接口公开c/c++代码(这句是百度来的,没有深入学习过,这几天的理解就是将编译的GDAL的C++库变成C#可用的库文件),SWIG并没有选择最新的版本,我也试过最新的,然而一大堆bug,刚接触,找不出问题根源。后来发现GDAL源码swig\csharp\gdal文件夹中随便打开一个.cs文件就会发现// * This file was automatically generated by SWIG (http://www.swig.org). * Version 2.0.12//这样的注释,所以选择了swigwin2.0.12,结果还真的成功了。

  1. 具体编译步骤

2.1 文件准备
将下载的gdal222.zip解压,我这里解压到文件夹E:\GDAL\gdal-2.2.2。然后将下载的HDF4.2.6_win_x86.zip,HDF5-1.8.7_win_x86.zip分别解压到路径E:\GDAL\supportlib\x86\HDF4.2.6_win_x86和E:\GDAL\supportlib\x86\HDF4.2.6_win_x86。再将下载的netCDF4.5.0-rc3-NC4-32.exe安装,并将安装路径下的bin,include,lib以及share文件夹拷贝到路径E:\GDAL\supportlib\x86\netCDF_4.5.0-rc3。最后将下载的swigwin-2.0.12.zip解压到路径E:\GDAL\swigwin-2.0.12。

2.2 系统环境变量设置
为了在编译时能顺利调用swig.exe,需要在系统属性>高级>环境变量中,编辑变量PATH,添加swig.exe所在路径,我这里添加路径E:\GDAL\swigwin-2.0.12。环境变量设置完成后,win+r运行窗口输入swig回车,看到一个黑窗口一闪而过说明设置成功。

2.3 gdal编译文件nmake.opt修改
用Notepad打开E:\GDAL\gdal-2.2.2路径下的nmake.opt文件,做以下修改:
(1)第48行,根据自己VS的版本将MSVC_VER改为相应的值,我这里的VS2012所以第48行改为MSVC_VER=1700;
(2)第64行,GDAL_HOME为编译结果路径,根据需要设置,默认为”C:\GDAL\warmerda\bld”,我这里改为”E:\GDAL\warmerda\bld”;
(3)第419-422行:

HDF4_PLUGIN = NO

HDF4_DIR = D:\warmerda\HDF41r5

HDF4_LIB = /LIBPATH:$(HDF4_DIR)\lib Ws2_32.lib

HDF4_INCLUDE = $(HDF4_DIR)\include

改为:
HDF4_PLUGIN = NO
HDF4_DIR = E:\GDAL\supportlib\x86\HDF4.2.6_win_x86
HDF4_LIB = (HDF4DIR)\dll\hd426m.lib(HDF4_DIR)\dll\hm426m.lib \
(HDF4DIR)\lib\hd426.lib(HDF4_DIR)\lib\hm426.lib Ws2_32.lib
HDF4_INCLUDE = $(HDF4_DIR)\include
注意:HDF4_DIR为2.1步HDF4.2.6_win_x86.zip解压到的路径;
(4)第430-432行:

HDF5_PLUGIN = NO

HDF5_DIR = c:\warmerda\supportlibs\hdf5\5-164-win

HDF5_LIB = $(HDF5_DIR)\dll\hdf5dll.lib

改为:
HDF5_PLUGIN = NO
HDF5_DIR = E:\GDAL\supportlib\x86\HDF5-1.8.7_win_x86
HDF5_LIB = $(HDF5_DIR)\dll\hdf5dll.lib
注意:HDF5_DIR 为2.1步HDF5-1.8.7_win_x86.zip解压到的路径;
(5)第521-524行:

NETCDF_PLUGIN = NO

NETCDF_SETTING=yes

NETCDF_LIB=C:\Software\netcdf\lib\netcdf.lib

NETCDF_INC_DIR=C:\Software\netcdf\include

改为:
NETCDF_PLUGIN = yes
NETCDF_SETTING=yes
NETCDF_LIB=E:\GDAL\supportlib\x86\netCDF_4.5.0-rc3\lib\netcdf.lib
NETCDF_INC_DIR=E:\GDAL\supportlib\x86\netCDF_4.5.0-rc3\include

2.4 C++编译
在程序中找到”VS2012 x86 本机工具命令提示“并运行,用cd命令将路径切换到GDAL源码目录,即解压gdal222.zip的目录,我这里是E:\GDAL\gdal-2.2.2。然后依次输入nmake /f makefile.vc,nmake /f makefile.vc install,nmake/f makefile.vc devinstall。三个命令执行成功后,在之前设置的GDAL_HOME路径(我这里是E:\GDAL\warmerda\bld)会出现bin,data,html,include,lib文件夹。其中bin文件夹中的gdal202.dll即我们需要的文件。

2.5 C#编译
在程序中找到”VS2012 x86 本机工具命令提示“并运行,用cd命令将路径切换到GDAL源码目录下的swig\csharp目录,我这里是E:\GDAL\gdal-2.2.2\swig\csharp。然后依次输入nmake /f makefile.vc interface,nmake /f makefile.vc,nmake /f makefile.vc install。三个命令执行成功后,在之前设置的GDAL_HOME路径(我这里是E:\GDAL\warmerda\bld)会出现csharp文件夹。其中的8个.dll文件即我们需要的文件。

2.6 库文件的使用
编写C#程序时,需要引用2.5节编译生成的gdal_csharp.dll,gdalconst_csharp.dll,ogr_csharp.dll和osr_csharp.dll。同时需要将2.4节生成的gdal202.dll,2.5节生成的8个.dll文件,以及E:\GDAL\supportlib\x86\HDF4.2.6_win_x86\dll文件夹、E:\GDAL\supportlib\x86\HDF4.2.6_win_x86\dll文件夹、E:\GDAL\supportlib\x86\netCDF_4.5.0-rc3\bin文件夹中的.dll文件全部拷贝到工程文件bin\x86\Debug文件夹下面。
附上编译好的C# GDAL库:http://download.csdn.net/download/crace1992/10045654

3 编译中的错误解决方案
在执行2.5节时可能会遇到以下问题:
3.1 接口重定义
osr\OsrPINVOKE.cs(192,10): error CS0111:
类型“OSGeo.OSR.OsrPINVOKE”已定义了一个名为“OsrPINVOKE”的具有相同参数类型的成员
osr\OsrPINVOKE.cs(188,10): (与前一个错误相关的符号位置)
NMAKE : fatal error U1077: “C:\Windows\Microsoft.NET\Framework\v4.0.30319\csc.EXE”: 返回代码“0x1”

解决方法是打开gdal2.2.2\swig\csharp\gdal|ogr|osr三个文件夹下,将GdalPINVOKE.cs,OgrPINVOKE.cs,OsrPINVOKE.cs中的相同GdalPINVOKE声明
static GdalPINVOKE() {
}
//static GdalPINVOKE() {
//}
注释掉一个;

3.2 接口名错误
gdal\Band.cs(17,79): error CS0117:
“OSGeo.GDAL.GdalPINVOKE”并不包含“BandUpcast”的定义
gdal\Dataset.cs(17,82): error CS0117:
“OSGeo.GDAL.GdalPINVOKE”并不包含“DatasetUpcast”的定义
gdal\Driver.cs(17,81): error CS0117:
“OSGeo.GDAL.GdalPINVOKE”并不包含“DriverUpcast”的定义
NMAKE : fatal error U1077: “C:\Windows\Microsoft.NET\Framework\v4.0.30319\csc.EXE”: 返回代码“0x1”

解决方法:将gdal2.2.2\swig\csharp\gdal文件夹下的Band.cs,Dataset.cs,Driver.cs中的GdalPINVOKE.BandUpcast,GdalPINVOKE.DatasetUpcast,GdalPINVOKE.DriverUpcast分别改为GdalPINVOKE.Band_SWIGUpcast,GdalPINVOKE.Dataset_SWIGUpcast,GdalPINVOKE.Driver_SWIGUpcast,即:
public Band(IntPtr cPtr, bool cMemoryOwn, object parent) : base(GdalPINVOKE.BandUpcast(cPtr), cMemoryOwn, parent) {
swigCPtr = new HandleRef(this, cPtr);
}
public Dataset(IntPtr cPtr, bool cMemoryOwn, object parent) : base(GdalPINVOKE.DatasetUpcast(cPtr), cMemoryOwn, parent) {
swigCPtr = new HandleRef(this, cPtr);
}
public Driver(IntPtr cPtr, bool cMemoryOwn, object parent) : base(GdalPINVOKE.DriverUpcast(cPtr), cMemoryOwn, parent) {
swigCPtr = new HandleRef(this, cPtr);
}
分别改为
public Band(IntPtr cPtr, bool cMemoryOwn, object parent) : base(GdalPINVOKE.Band_SWIGUpcast(cPtr), cMemoryOwn, parent) {
swigCPtr = new HandleRef(this, cPtr);
}
public Dataset(IntPtr cPtr, bool cMemoryOwn, object parent) : base(GdalPINVOKE.Dataset_SWIGUpcast(cPtr), cMemoryOwn, parent) {
swigCPtr = new HandleRef(this, cPtr);
}
public Driver(IntPtr cPtr, bool cMemoryOwn, object parent) : base(GdalPINVOKE.Driver_SWIGUpcast(cPtr), cMemoryOwn, parent) {
swigCPtr = new HandleRef(this, cPtr);
}

原创粉丝点击