• Inside GDALAllRegister之二: 自动加载驱动


    代码    GetGDALDriverManager()->AutoLoadDrivers(); 包含了两部分:

    首先获得GDALDriverManager的singleton对象的指针,这点之前已经说明过,采用DCLP是个错误用法,不过可以通过下面的方法规避:

    永远只在main函数内部单线程调用一次GDALAllRegister, 在其他线程尚未创建之前,singleton对象已经被创建出来


    然后运行void GDALDriverManager::AutoLoadDrivers() 函数。这是本次分析的主要内容。注释写的不错,很容易就理解了该函数的逻辑。

    /**
     * rief Auto-load GDAL drivers from shared libraries.
     *
     * This function will automatically load drivers from shared libraries.  It
     * searches the "driver path" for .so (or .dll) files that start with the
     * prefix "gdal_X.so".  It then tries to load them and then tries to call a
     * function within them called GDALRegister_X() where the 'X' is the same as
     * the remainder of the shared library basename ('X' is case sensitive), or
     * failing that to call GDALRegisterMe().
     *
     * There are a few rules for the driver path.  If the GDAL_DRIVER_PATH
     * environment variable it set, it is taken to be a list of directories to
     * search separated by colons on UNIX, or semi-colons on Windows.  Otherwise
     * the /usr/local/lib/gdalplugins directory, and (if known) the
     * lib/gdalplugins subdirectory of the gdal home directory are searched on
     * UNIX and $(BINDIR)gdalplugins on Windows.
     */


    该函数在driver path中查找文件名为gdal_X.dll或者gdal_X.so的动态库文件。如果找到,就加载该动态库,并调用其中的GDALResiter_X()函数,每隔动态库都应该实现这个函数。X代表库的名称。

    driver path可以通过设置环境变量GDAL_DRIVER_PATH来获得,path之间通过,或者;分隔。 如果没有设定环境变量,就使用默认查找路径:/usr/local/lib/gdalplugins, 

    并且:

    1. 如果Unix下有gdal home 目录的话,还会找该目录下的lib/gdalplugins子目录,

    2. 如果windows下会用$(BINDDIR)gdalplugins 作为查找路径。这里$(BINDIR)值得是当前进程所在目录。

    下面是全部代码:

    void GDALDriverManager::AutoLoadDrivers()
    
    {
        char     **papszSearchPath = NULL;
        const char *pszGDAL_DRIVER_PATH = 
            CPLGetConfigOption( "GDAL_DRIVER_PATH", NULL );
    
    /* -------------------------------------------------------------------- */
    /*      Where should we look for stuff?                                 */
    /* -------------------------------------------------------------------- */
        if( pszGDAL_DRIVER_PATH != NULL )
        {
    #ifdef WIN32
            papszSearchPath = 
                CSLTokenizeStringComplex( pszGDAL_DRIVER_PATH, ";", TRUE, FALSE );
    #else
            papszSearchPath = 
                CSLTokenizeStringComplex( pszGDAL_DRIVER_PATH, ":", TRUE, FALSE );
    #endif
        }
        else
        {
    #ifdef GDAL_PREFIX
            papszSearchPath = CSLAddString( papszSearchPath, 
        #ifdef MACOSX_FRAMEWORK
                                            GDAL_PREFIX "/PlugIns");
        #else
                                            GDAL_PREFIX "/lib/gdalplugins" );
        #endif
    #else
            char szExecPath[1024];
    
            if( CPLGetExecPath( szExecPath, sizeof(szExecPath) ) )
            {
                char szPluginDir[sizeof(szExecPath)+50];
                strcpy( szPluginDir, CPLGetDirname( szExecPath ) );
                strcat( szPluginDir, "\gdalplugins" );
                papszSearchPath = CSLAddString( papszSearchPath, szPluginDir );
            }
            else
            {
                papszSearchPath = CSLAddString( papszSearchPath, 
                                                "/usr/local/lib/gdalplugins" );
            }
    #endif
    
       #ifdef MACOSX_FRAMEWORK
       #define num2str(x) str(x)
       #define str(x) #x 
         papszSearchPath = CSLAddString( papszSearchPath, 
                                         "/Library/Application Support/GDAL/"
                                         num2str(GDAL_VERSION_MAJOR) "."  
                                         num2str(GDAL_VERSION_MINOR) "/PlugIns" );
       #endif
    
    
            if( strlen(GetHome()) > 0 )
            {
                papszSearchPath = CSLAddString( papszSearchPath, 
                                      CPLFormFilename( GetHome(),
        #ifdef MACOSX_FRAMEWORK 
                                         "/Library/Application Support/GDAL/"
                                         num2str(GDAL_VERSION_MAJOR) "."  
                                         num2str(GDAL_VERSION_MINOR) "/PlugIns", NULL ) );
        #else
                                                        "lib/gdalplugins", NULL ) );
        #endif                                           
            }
        }
    
    /* -------------------------------------------------------------------- */
    /*      Scan each directory looking for files starting with gdal_       */
    /* -------------------------------------------------------------------- */
        for( int iDir = 0; iDir < CSLCount(papszSearchPath); iDir++ )
        {
            char  **papszFiles = CPLReadDir( papszSearchPath[iDir] );
    
            for( int iFile = 0; iFile < CSLCount(papszFiles); iFile++ )
            {
                char   *pszFuncName;
                const char *pszFilename;
                const char *pszExtension = CPLGetExtension( papszFiles[iFile] );
                void   *pRegister;
    
    #if ( defined( _WIN32 ) && ( defined(DEBUG) || defined(_DEBUG) ) )
                if( !EQUALN(papszFiles[iFile],"debug_gdal_",11) )
                    continue;
    #else
                if( !EQUALN(papszFiles[iFile],"gdal_",5) )
                    continue;
    #endif
    
                if( !EQUAL(pszExtension,"dll") 
                    && !EQUAL(pszExtension,"so") 
                    && !EQUAL(pszExtension,"dylib") )
                    continue;
    
                pszFuncName = (char *) CPLCalloc(strlen(papszFiles[iFile])+20,1);
    #if ( defined( _WIN32 ) && ( defined(DEBUG) || defined(_DEBUG) ) )
                CPLString sName = CPLGetBasename(papszFiles[iFile]) + 11;
    #else
                CPLString sName = CPLGetBasename(papszFiles[iFile]) + 5;
    #endif
                sprintf( pszFuncName, "GDALRegister_%s", sName.c_str() );
                pszFilename = 
                    CPLFormFilename( papszSearchPath[iDir], 
                                     papszFiles[iFile], NULL );
    
                pRegister = CPLGetSymbol( pszFilename, pszFuncName );
                if( pRegister == NULL )
                {
                    sName.toupper();
                    sprintf( pszFuncName, "GDALRegister_%s", sName.c_str() );
                    pRegister = CPLGetSymbol( pszFilename, pszFuncName );
                    if( pRegister == NULL )
                    {
                        strcpy( pszFuncName, "GDALRegisterMe" );
                        pRegister = CPLGetSymbol( pszFilename, pszFuncName );
                    }
                }
                
                if( pRegister != NULL )
                {
                    CPLDebug( "GDAL", "Auto register %s using %s.", 
                              pszFilename, pszFuncName );
    
                    ((void (*)()) pRegister)();
                }
    
                CPLFree( pszFuncName );
            }
    
            CSLDestroy( papszFiles );
        }
    
        CSLDestroy( papszSearchPath );
    }


    那个查找目录树的算法算不上糟糕,不过用惯了boost和newlisp的我,看到不禁皱眉头。太不优雅了。一帮C程序员在写C++代码,循环之后还要用CSLFree和CSLDestory 释放内存,有string不用。就算不用string,也可以自己写个简单的class啊。

    很明显,GDAL的源代码并没有随着C++语言的发展而进步,让我不仅想起了ACE。

    调试一遍后,发现我的GDAL代码在这里没有加载任何驱动。就是我想要的结果。:)

  • 相关阅读:
    Storm 第一章 核心组件及编程模型
    四 Hive整合HBase
    Hbase第五章 MapReduce操作HBase
    swift 附属脚本
    swift 方法
    swift 属性
    swift 类和结构体
    swift 枚举类型
    swift 闭包
    Swift 函数
  • 原文地址:https://www.cnblogs.com/keanuyaoo/p/3257837.html
Copyright © 2020-2023  润新知