zoukankan      html  css  js  c++  java
  • 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:GDALGDALGDAL232“”),如图所示:

    3、修改“D:GDALgdal-2.3.2 make.opt”文件,如下图:

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

    • 修改57行,GDAL_HOME = "D:GDALGDALGDAL232"(编译后文件的生成目录)
    • 修改86行,SWIG = D:GDALswigwin-3.0.12swig.exe(这个必须是完全路径)
    • 修改184行,去掉“#”,效果为WIN64=YES
    • 修改960行,去掉后边的下划线,效果为SYM_PREFIX=

    二、编译C++

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

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

    然后依次输入:

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

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

    三、编译C#

    1、修改C#源码文件

    打开“D:GDALgdal-2.3.2swigcsharpAssemblyInfo.cs”,注释掉【[assembly: AllowPartiallyTrustedCallers]】,如下图所示:

     打开如下三个文件:

    • “D:GDALgdal-2.3.2swigcsharpgdalGdalPINVOKE.cs”
    • “D:GDALgdal-2.3.2swigcsharpogrOgrPINVOKE.cs”
    • “D:GDALgdal-2.3.2swigcsharposrOsrPINVOKE.cs”

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

             

    打开如下三个文件:

    • “D:GDALgdal-2.3.2swigcsharpgdalBand.cs”
    • “D:GDALgdal-2.3.2swigcsharpgdalDataset.cs”
    • “D:GDALgdal-2.3.2swigcsharpgdalDriver.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:GDALgdal-2.3.2swigcsharpconstGdalConstPINVOKE.cs”
    • “D:GDALgdal-2.3.2swigcsharpgdalGdalPINVOKE.cs”
    • “D:GDALgdal-2.3.2swigcsharpogrOgrPINVOKE.cs”
    • “D:GDALgdal-2.3.2swigcsharposrOsrPINVOKE.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:GDALgdal-2.3.2swigcsharpgdalGdal.cs”
    • “D:GDALgdal-2.3.2swigcsharpogrOgr.cs”
    • “D:GDALgdal-2.3.2swigcsharposrOsr.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); }

    2、编译

         输入cd swigcsharp ,切换到csharp目录,

         输入nmake /f makefile.vc(运行这一步有问题的话,加以下两句:namke /f makefile.vc clear 、nmake /f makefile.vc interface)

         输入nmake /f makefile.vc install 

    编译完成后,在目录“D:GDALGDALGDAL232csharp”会生成8个文件,如图所示:

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

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

    四、测试DLL

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

    把“D:GDALGDALGDAL232csharp”中的8个dll和“D:GDALGDALGDAL232in”中的一个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;
    }

    效果如图所示:

  • 相关阅读:
    Eclipse 安装配置指南
    CentOS下安装Git
    MySQL5.5在Windows下的安装
    NSInvocation调用
    动态调用
    模拟静态变量及静态类继承
    respondsToSelector判断是否实现了某方法
    JAVA闭包
    IMP获取函数指针
    [链表] 对链表与文件的结合使用的一点看法
  • 原文地址:https://www.cnblogs.com/aizai846/p/9729252.html
Copyright © 2011-2022 走看看