Wechat: yu389741| Email: gisdqy@163.com

Shop:https://www.giserdqy.com/shop

GDAL中的进度条



GDAL中调用进度条函数都是以回调函数指针形式调用的,这里先介绍下回调函数。

函数指针

函数指针指向的是函数而非对象。
声明一个指向函数的函数指针,只需要用指针替换函数名即可:

  void (*pfn) (string s1);

注:pfn两边的括号不能去掉

使用函数指针

当我们把函数名作为值使用时,会自动转换为指针。
现在有个函数声明为为:void strCompare(string s1);

pfn = strCompare;//函数名strCompare作为值使用,则自动转换为指针,赋值给pfn.
pfn = &strCompare;//也可以对函数取地址。

以下三个语句是等价调用:

     1) pfn(“meng”);
     2)(*pfn)(“meng”);
     3) strCompare(“meng”);

回调函数

这里说明一下,当用数组或者函数作为形参时,实际上是当做指针使用,如果传递数组时,实际上传递的是指向数组首元素的指针,如果传递函数时,实际上是作为函数指针使用
例如:

void caller(string s, void fn(string str));//第二个形参会自动的转换为指向函数的指针。
void caller(string s, void (*fn)(string str));//显示的定义函数指针,两句代码等价。

下面的pfn表明是函数指针:

typedef void(*pfn)(const char* str);

下面就用GDAL中的进度条来说明回调函数的使用方法。

GDAL中的进度条

gdal中的进度条函数声明原型:

int CPL_STDCALL GDALTermProgress( CPL_UNUSED double dfComplete,
                                  CPL_UNUSED const char *pszMessage,
                                  void * /* pProgressArg */ )

GDALTermProgress函数的源代码(在源代码的\gdal-2.1.2\port\cpl_progress.cpp):

int CPL_STDCALL GDALTermProgress( CPL_UNUSED double dfComplete,
                                  CPL_UNUSED const char *pszMessage,
                                  void * /* pProgressArg */ )
{
    int nThisTick = std::min(40, std::max(0,
        static_cast<int>(dfComplete * 40.0) ));
    // Have we started a new progress run?
    static int nLastTick = -1;
    if( nThisTick < nLastTick && nLastTick >= 39 )
        nLastTick = -1;
    if( nThisTick <= nLastTick )
        return TRUE;
    while( nThisTick > nLastTick )
    {
        ++nLastTick;
        if( nLastTick % 4 == 0 )
            fprintf( stdout, "%d", (nLastTick / 4) * 10 );
        else
            fprintf( stdout, "." );
    }
    if( nThisTick == 40 )
        fprintf( stdout, " - done.\n" );
    else
        fflush( stdout );
    return TRUE;
}

下面我就用一个简单的例子来使用该函数:

#include "stdafx.h"
#include <iostream>
#include <algorithm>
using namespace std;
typedef int(*MyProgress)(double dfComplete,const char *pszMessage, void *  pProgressArg );//声明函数指针
int  Progress(double dfComplete,const char *pszMessage,void *  pProgressArg );//函数声明

void print(int Size, MyProgress callback, void * pProgressArg);//回调函数

MyProgress pfnProgress = Progress; //定义函数指针变量并初始化
int _tmain(int argc, _TCHAR* argv[])
{
    void * pProgressArg = NULL;
    int nYSize = 1000000;
    print(nYSize, pfnProgress, pProgressArg);

    getchar();
    return 0;
}
/*
Size:一般表示实际的长度,大小,比如波段的高等。
callback:指向进度条函数
pProgressArg:要显示的信息。
*/
void print(int Size, MyProgress callback, void * pProgressArg)
{
    for (int i = 0; i < Size; i++)
    {
        pfnProgress(0.10 + 0.9 * ((i + 1) / (double)Size),
            "", pProgressArg);//
    }
}
//该段代码就是上面GDALTermProgress函数的源代码。
int  Progress(double dfComplete,
                   const char *pszMessage,
                   void * pProgressArg )
{
    int nThisTick = std::min(40, std::max(0,
        static_cast<int>(dfComplete * 40.0)));
    // Have we started a new progress run?
    static int nLastTick = -1;
    if (nThisTick < nLastTick && nLastTick >= 39)
        nLastTick = -1;
    if (nThisTick <= nLastTick)
        return true;
    while (nThisTick > nLastTick)
    {
        ++nLastTick;
        if (nLastTick % 4 == 0)
            fprintf(stdout, "%d", (nLastTick / 4) * 10);
        else
            fprintf(stdout, ".");
    }
    if (nThisTick == 40)
        fprintf(stdout, " - done.\n");
    else
        fflush(stdout);
    return true;
}

运行结果:
这里写图片描述

下面来看看GDAL中是怎么使用进度条的。
GDALPolygonizeT函数是栅格矢量化函数,可以在源代码的\gdal-2.1.2\alg\polygonize.cpp中查看源码,在437行左右。

template<class DataType, class EqualityTest>
static CPLErr
GDALPolygonizeT( GDALRasterBandH hSrcBand,
                 GDALRasterBandH hMaskBand,
                 OGRLayerH hOutLayer, int iPixValField,
                 char **papszOptions,
                 GDALProgressFunc pfnProgress,
                 void * pProgressArg,
                 GDALDataType eDT)

GDALProgressFunc就是一个指向进度条函数的函数指针。
下面是源码中的使用(在664行左右):

/* -------------------------------------------------------------------- */
/*      Report progress, and support interrupts.                        */
/* -------------------------------------------------------------------- */
if( eErr == CE_None
            && !pfnProgress( 0.10 + 0.90 * ((iY+1) / (double) nYSize),
                             "", pProgressArg ) )
        {
            CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
            eErr = CE_Failure;
        }

转载自:https://blog.csdn.net/u010670734/article/details/53787446