GDAL中的进度条

来源:互联网 发布:宁波 大数据开发 招聘 编辑:程序博客网 时间:2024/05/16 12:46

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 CPLErrGDALPolygonizeT( 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;        }
0 0
原创粉丝点击