VS2017編譯GDAL(64bit)+解決C#讀取Shp數據中文路徑的問題


編譯GDAL過程比較繁瑣,查閱了網上相關資料,同時經過實踐,完成GDAL的編譯,同時解決了SHP數據中文路徑及中文字段亂碼的問題,本文以「gdal-2.3.2」版本爲例闡述整個編譯過程。函數

1、編譯準備工具

一、編譯工具是VS2017,編譯前須要下載「gdal-2.3.2」和「swigwin-3.0.12」,下載連接以下:測試

  • GDAL:http://trac.osgeo.org/gdal/wiki/DownloadSource
  • swigwin:https://sourceforge.net/projects/swig/files/swigwin/

二、在「D盤」新建目錄「GDAL」,將兩個壓縮包解壓到該目錄中,同時新建一個文件夾用於存放編譯結果(如「D:\GDAL\GDAL\GDAL232「」),如圖所示:this

三、修改「D:\GDAL\gdal-2.3.2\nmake.opt」文件,以下圖:spa

 

文件「nmake.opt」修改以下:.net

  • 修改57行,GDAL_HOME = "D:\GDAL\GDAL\GDAL232"(編譯後文件的生成目錄)
  • 修改86行,SWIG = D:\GDAL\swigwin-3.0.12\swig.exe(這個必須是徹底路徑)
  • 修改184行,去掉「#」,效果爲WIN64=YES
  • 修改960行,去掉後邊的下劃線,效果爲SYM_PREFIX=

2、編譯C++code

以管理員運行【開始】-【全部程序】-【Visual Studio 2017】-【Visual Studio Tools】-【VC】-【適用於 VS 2017 的 x64 本機工具命令提示】菜單,彈出命令框如圖所示:orm

輸入cd D:\GDAL\gdal-2.3.2 切換至gdal-2.3.2目錄,如圖所示:blog

而後依次輸入:接口

  • nmake /f makefile.vc
  • nmake /f makefile.vc install
  • nmake /f makefile.vc devinstall

C++編譯時間較長,須要耐心等待……

3、編譯C#

一、修改C#源碼文件

打開「D:\GDAL\gdal-2.3.2\swig\csharp\AssemblyInfo.cs」,註釋掉【[assembly: AllowPartiallyTrustedCallers]】,以下圖所示:

 打開以下三個文件:

  • 「D:\GDAL\gdal-2.3.2\swig\csharp\gdal\GdalPINVOKE.cs」
  • 「D:\GDAL\gdal-2.3.2\swig\csharp\ogr\OgrPINVOKE.cs」
  • 「D:\GDAL\gdal-2.3.2\swig\csharp\osr\OsrPINVOKE.cs」

分別註釋掉重複的構造函數,如圖所示:

         

打開以下三個文件:

  • 「D:\GDAL\gdal-2.3.2\swig\csharp\gdal\Band.cs」
  • 「D:\GDAL\gdal-2.3.2\swig\csharp\gdal\Dataset.cs」
  • 「D:\GDAL\gdal-2.3.2\swig\csharp\gdal\Driver.cs」

文件,修改接口成員(大概17行),以下:

 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.Band_SWIGUpcast(cPtr), cMemoryOwn, parent){swigCPtr = new HandleRef(this, cPtr);}

 public Driver(IntPtr cPtr, bool cMemoryOwn, object parent): base(GdalPINVOKE.Band_SWIGUpcast(cPtr), cMemoryOwn, parent){swigCPtr = new HandleRef(this, cPtr);} 

接下來解決讀取中文路徑及屬性亂碼 :

打開以下四個文件:

  • 「D:\GDAL\gdal-2.3.2\swig\csharp\const\GdalConstPINVOKE.cs」
  • 「D:\GDAL\gdal-2.3.2\swig\csharp\gdal\GdalPINVOKE.cs」
  • 「D:\GDAL\gdal-2.3.2\swig\csharp\ogr\OgrPINVOKE.cs」
  • 「D:\GDAL\gdal-2.3.2\swig\csharp\osr\OsrPINVOKE.cs」

分別修改類「SWIGStringHelper」(大概168行),具體代碼(紅色爲修改過得代碼)以下:

 

protected class SWIGStringHelper {

public delegate string SWIGStringDelegate(IntPtr message);
static SWIGStringDelegate stringDelegate = new SWIGStringDelegate(CreateString);

[global::System.Runtime.InteropServices.DllImport("ogr_wrap", EntryPoint="SWIGRegisterStringCallback_Ogr")]
public static extern void SWIGRegisterStringCallback_Ogr(SWIGStringDelegate stringDelegate);

static string CreateString(IntPtr pNativeData) { if (pNativeData == IntPtr.Zero) return ""; int i = 0; byte[] strbuf1 = new byte[1]; Marshal.Copy(pNativeData + i, strbuf1, 0, 1); while (strbuf1[0] != 0) { i++; strbuf1 = new byte[1]; Marshal.Copy(pNativeData + i, strbuf1, 0, 1); } int length = i;//循環查找字符串的長度

byte[] strbuf = new byte[length]; Marshal.Copy(pNativeData, strbuf, 0, length); return System.Text.Encoding.UTF8.GetString(strbuf); } static SWIGStringHelper() {
SWIGRegisterStringCallback_Ogr(stringDelegate);
}
}

打開以下三個文件:

  • 「D:\GDAL\gdal-2.3.2\swig\csharp\gdal\Gdal.cs」
  • 「D:\GDAL\gdal-2.3.2\swig\csharp\ogr\Ogr.cs」
  • 「D:\GDAL\gdal-2.3.2\swig\csharp\osr\Osr.cs」

分別修改函數「Utf8BytesToString」,代碼以下:

internal static string Utf8BytesToString(IntPtr pNativeData)
{
if (pNativeData == IntPtr.Zero) return null; int i = 0; byte[] strbuf1 = new byte[1]; Marshal.Copy(pNativeData + i, strbuf1, 0, 1); while (strbuf1[0] != 0) { i++; strbuf1 = new byte[1]; Marshal.Copy(pNativeData + i, strbuf1, 0, 1); } int length = i;//循環查找字符串的長度 byte[] strbuf = new byte[length]; Marshal.Copy(pNativeData, strbuf, 0, length); //int length = Marshal.PtrToStringAnsi(pNativeData).Length; //byte[] strbuf = new byte[length]; //Marshal.Copy(pNativeData, strbuf, 0, length); return System.Text.Encoding.UTF8.GetString(strbuf); }

二、編譯

     輸入cd swig\csharp ,切換到csharp目錄,

     輸入nmake /f makefile.vc(運行這一步有問題的話,加如下兩句:namke /f makefile.vc clear 、nmake /f makefile.vc interface)

     輸入nmake /f makefile.vc install 

編譯完成後,在目錄「D:\GDAL\GDAL\GDAL232\csharp」會生成8個文件,如圖所示:

注:C#編譯過程當中,若是出現HandleRef和IntPtr沒有引用的錯誤,只須要在相應文件中添加命名空間

using System;
using System.Runtime.InteropServices;便可解決該問題

4、測試DLL

新建一個Winform應用程序,修改運行配置爲x64,如圖所示:

把「D:\GDAL\GDAL\GDAL232\csharp」中的8個dll和「D:\GDAL\GDAL\GDAL232\bin」中的一個dll複製到「x64/Release」目錄下,添加引用

讀取Shp數據的代碼以下:

OSGeo.GDAL.Gdal.AllRegister();
OSGeo.OGR.Ogr.RegisterAll();
OSGeo.OGR.Driver dr = OSGeo.OGR.Ogr.GetDriverByName("ESRI shapefile");
OSGeo.OGR.DataSource ds = dr.Open(path, 0);

if (ds == null)
{
MessageBox.Show("文件不能打開,請檢查!");
return;
}

 

效果如圖所示:

相關文章
相關標籤/搜索