代码 GetGDALDriverManager()->AutoLoadDrivers(); 包含了两部分:
首先获得GDALDriverManager的singleton对象的指针,这点之前已经说明过,采用DCLP是个错误用法,不过可以通过下面的方法规避:
永远只在main函数内部单线程调用一次GDALAllRegister, 在其他线程尚未创建之前,singleton对象已经被创建出来
然后运行void GDALDriverManager::AutoLoadDrivers() 函数。这是本次分析的主要内容。注释写的不错,很容易就理解了该函数的逻辑。
/** * \brief 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_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 ); }
很明显,GDAL的源代码并没有随着C++语言的发展而进步,让我不仅想起了ACE。
调试一遍后,发现我的GDAL代码在这里没有加载任何驱动。就是我想要的结果。:)