Inside GDALAllRegister之二: 自动加载驱动
来源:互联网 发布:斯大林大战火星人2知乎 编辑:程序博客网 时间:2024/06/03 16:42
代码 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_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代码在这里没有加载任何驱动。就是我想要的结果。:)
- Inside GDALAllRegister之二: 自动加载驱动
- Inside GDALAllRegister之三: 注册指定驱动
- Inside GDALAllRegister之四: 跳过driver
- Inside GDALAllRegister之一: 五大部分
- JDBC详解系列(二)之加载驱动
- Windows驱动_文件系统微小过滤驱动之二驱动的安装和加载
- Zend Framework 自动加载之二:目标和设计
- 驱动学习笔记二:加载驱动
- PHP之自动加载
- php之自动加载
- Android之实现ListView的“下拉刷新”、“上拉加载”、“自动加载”功能(二)
- fC下网卡驱动自动加载
- WINCE流驱动的自动加载
- WINCE流驱动的自动加载
- linux 下开机自动加载驱动模块
- linux 下开机自动加载驱动模块
- WINCE流驱动的自动加载
- tiny6410 驱动模块开机自动加载
- Trie 树
- automake的简单介绍
- win7(x64)安装android studio失败(jdk未找到)
- java环境变量配置
- UpdateData函数的使用
- Inside GDALAllRegister之二: 自动加载驱动
- MFC打开文件对话框
- Linux power management: The documentation I wanted to read
- 修改Windows和linux系统时间
- 根据位置来触发单击事件
- (step4.1.3)hdu 2438(Turn the corner——三分查找)
- iOS常用控件尺寸大集合
- iOS5新开发的API总述
- VC 链接时new和delete运算符已经在 LIBCMTD.lib 中定义解决方法