shp文件奥秘及c语言编程对策,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/

2、在“D盘”新建目录“GDAL”,将两个压缩包解压到该目录中,同时新建一个文件夹用于存放编译结果(如“D:\GDAL\GDAL\GDAL232“”),如图所示:

5e86010c3182e11270d82d954c316822.png

3、修改“D:\GDAL\gdal-2.3.2\nmake.opt”文件,如下图:

a4c72605a8cc77241ae276c1249859de.png

文件“nmake.opt”修改如下:

修改57行,GDAL_HOME = "D:\GDAL\GDAL\GDAL232"(编译后文件的生成目录)

修改86行,SWIG = D:\GDAL\swigwin-3.0.12\swig.exe(这个必须是完全路径)

修改184行,去掉“#”,效果为WIN64=YES

修改960行,去掉后边的下划线,效果为SYM_PREFIX=

二、编译C++

以管理员运行【开始】-【所有程序】-【Visual Studio 2017】-【Visual Studio Tools】-【VC】-【适用于 VS 2017 的 x64 本机工具命令提示】菜单,弹出命令框如图所示:

2cd65eb278870248d163ec3affd172cf.png

输入cd D:\GDAL\gdal-2.3.2 切换至gdal-2.3.2目录,如图所示:

6afe5fca13bfbb8ab6584c5df226267e.png

然后依次输入:

nmake /f makefile.vc

nmake /f makefile.vc install

nmake /f makefile.vc devinstall

C++编译时间较长,需要耐心等待……

三、编译C#

1、修改C#源码文件

打开“D:\GDAL\gdal-2.3.2\swig\csharp\AssemblyInfo.cs”,注释掉【[assembly: AllowPartiallyTrustedCallers]】,如下图所示:

c30d88edfb5bd73909224b095d8edc82.png

打开如下三个文件:

“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”

分别注释掉重复的构造函数,如图所示:

43a47697196211cc7436de9e6746150e.png

打开如下三个文件:

“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 classSWIGStringHelper {public delegate stringSWIGStringDelegate(IntPtr message);static SWIGStringDelegate stringDelegate = newSWIGStringDelegate(CreateString);

[global::System.Runtime.InteropServices.DllImport("ogr_wrap", EntryPoint="SWIGRegisterStringCallback_Ogr")]public static extern voidSWIGRegisterStringCallback_Ogr(SWIGStringDelegate stringDelegate);static stringCreateString(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);returnSystem.Text.Encoding.UTF8.GetString(strbuf);

}staticSWIGStringHelper() {

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 stringUtf8BytesToString(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);

returnSystem.Text.Encoding.UTF8.GetString(strbuf);

}

2、编译

输入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个文件,如图所示:

1077602678f6eb0e9f76c5e78106389f.png

注:C#编译过程中,如果出现HandleRef和IntPtr没有引用的错误,只需要在相应文件中添加命名空间

using System;

using System.Runtime.InteropServices;即可解决该问题

四、测试DLL

新建一个Winform应用程序,修改运行配置为x64,如图所示:

9f677d4cc669b347da0e8d6b27a2f8be.png

把“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;

}

效果如图所示:

669cab2ee8e4776a1cfcd8e773d07a6d.png

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值