Inside GDALAllRegister之二: 自动加载驱动
代码 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之二: 自动加载驱动的更多相关文章
- 简单实现JDBC自动加载驱动,简化数据连接和关闭数据库连接
package util; import java.io.File;import java.io.FileInputStream;import java.io.IOException;import j ...
- CAD 二次开发 -- 自动加载开发的DLL
CAD二次开发可以采用写扩展DLL的方式实现.该DLL的函数可以被CAD调用. 但是调用前,必须用命令netload 将该dll加载到CAD. 其实可以修改注册表,当CAD软件启动后,自动加载扩展DL ...
- linux下自动加载设备驱动程序模块
假设你的设备驱动程序为:yourdrivername.ko 1 cp yourdrivername.ko /lib/modules/"version"/kernel/driver ...
- JDBC详解系列(二)之加载驱动
---[来自我的CSDN博客](http://blog.csdn.net/weixin_37139197/article/details/78838091)--- 在JDBC详解系列(一)之流程中 ...
- FMX StringGrid向上滑动自动加载记录(二)
写完FMX StringGrid向上滑动自动加载记录(一)自己也觉得不理想,实现的别扭与复杂,现在找到更好的实现方法,原来,StringGrid从基类TCustomPresentedScrollBox ...
- C118 免按开机自动加载固件
最近无事,研究了按按钮开机的功能:功能的起初是参考了别人的系统是怎么做免开机加载固件的. 一.原理: 1.c118 原生loader部分代码是没有源代码的,它上电只需要按开机键然后系统就会起来. 2. ...
- 构建自己的PHP框架之自动加载类中详解spl_autoload_register()函数
在了解这个函数之前先来看另一个函数:__autoload. 一.__autoload 这是一个自动加载函数,在PHP5中,当我们实例化一个未定义的类时,就会触发此函数.看下面例子: printit.c ...
- autocad2008+C#2008开发中设置自动加载dll
一.复制编译后的dlll路径,比如我的是D:\zjy\cad开发\学习\宗地图\bin\Debug\zd.dll 二.随便找个地方新建一个记事本,在记事本中写入以下内容: (command " ...
- ajax的使用:(ajaxReturn[ajax的返回方法]),(eval返回字符串);分页;第三方类(page.class.php)如何载入;自动加载函数库(functions);session如何防止跳过登录访问(构造函数说明)
一.ajax例子:ajaxReturn("ok","eval")->thinkphp中ajax的返回值的方法,返回参数为ok,返回类型为eval(字符串) ...
随机推荐
- JVM CPU占满问题定位
RASP加载后出现JVM CPU占满问题,jstack -F输出信息无法找到对应占用CPU的线程 perf定位到占用CPU的热代码位于Dependencies::find_finalizable_su ...
- WinlogonHack获取系统密码
实验环境: win03 sp1 Gina.dll与Msgina.dll Gina.dll在NT/2000中交互式的登陆支持是由WinLogon调用Gina.dll实现的,Gina.dll提供了一个交互 ...
- 2018-2019-2 20162318《网络攻防技术》Exp5 MSF基础应用
1.实验内容 1.一个主动攻击实践,如ms08_067 2. 一个针对浏览器的攻击,如ms11_050) 3. 一个针对客户端的攻击,如Adobe 4. 成功应用任何一个辅助模块 2.基础问题回答 2 ...
- [BJOI2010]次小生成树
OJ题号: BZOJ1977.COGS2453 题目大意: 给你一个无向连通图,求严格次小生成树. 思路: 对于一般次小生成树,我们有一个结论:一般次小生成树一定可以通过替换掉最小生成树某一条边得到. ...
- .net mvc控制器传递方法到视图
很多人都是在视图里面定义方法,然后再使用.我个人也是这么干的.但是为了验证是否可以将方法从控制器传递到视图,所以做了个测试.结果真的可以.原理是利用了委托(delegate),因为委托本身就是一种类型 ...
- DOM-XML(解析与创建)
/** * 读取(解析)xml文件 * @author Administrator * */ public class DOMRead { public static void main(String ...
- 模拟拖拽图片 碰撞检测 DOM 鼠标事件 闭包
<!doctype html><html lang="en"> <head> <meta charset="UTF-8" ...
- [JAVA] JAVA JDK 安装配置
JDK 安装 下载安装 下载JDK 从oracle官方网站下载并安装JDK. 下载使用文档 从oracle官方网站下载使用帮助文档. 安装库源文件 源文件位于安装目录的 /Library/Java/J ...
- Android证书有效性验证方案
1.前言: 1.1.SSL劫持攻击: 目前虽然很多Android APP使用了https通信方式,但是只是简单的调用而已,并未对SSL证书有效性做验证.在攻击者看来,这种漏洞让htt ...
- android aapt 用法 -- ApkReader
aapt 是android assert packaging tool的缩写,具体如下: 1. 列出apk包的内容 aapt l[ist] [-v] [-a] file.{zip,jar,apk} - ...