代码    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之二: 自动加载驱动的更多相关文章

  1. 简单实现JDBC自动加载驱动,简化数据连接和关闭数据库连接

    package util; import java.io.File;import java.io.FileInputStream;import java.io.IOException;import j ...

  2. CAD 二次开发 -- 自动加载开发的DLL

    CAD二次开发可以采用写扩展DLL的方式实现.该DLL的函数可以被CAD调用. 但是调用前,必须用命令netload 将该dll加载到CAD. 其实可以修改注册表,当CAD软件启动后,自动加载扩展DL ...

  3. linux下自动加载设备驱动程序模块

    假设你的设备驱动程序为:yourdrivername.ko  1 cp yourdrivername.ko /lib/modules/"version"/kernel/driver ...

  4. JDBC详解系列(二)之加载驱动

    ---[来自我的CSDN博客](http://blog.csdn.net/weixin_37139197/article/details/78838091)---   在JDBC详解系列(一)之流程中 ...

  5. FMX StringGrid向上滑动自动加载记录(二)

    写完FMX StringGrid向上滑动自动加载记录(一)自己也觉得不理想,实现的别扭与复杂,现在找到更好的实现方法,原来,StringGrid从基类TCustomPresentedScrollBox ...

  6. C118 免按开机自动加载固件

    最近无事,研究了按按钮开机的功能:功能的起初是参考了别人的系统是怎么做免开机加载固件的. 一.原理: 1.c118 原生loader部分代码是没有源代码的,它上电只需要按开机键然后系统就会起来. 2. ...

  7. 构建自己的PHP框架之自动加载类中详解spl_autoload_register()函数

    在了解这个函数之前先来看另一个函数:__autoload. 一.__autoload 这是一个自动加载函数,在PHP5中,当我们实例化一个未定义的类时,就会触发此函数.看下面例子: printit.c ...

  8. autocad2008+C#2008开发中设置自动加载dll

    一.复制编译后的dlll路径,比如我的是D:\zjy\cad开发\学习\宗地图\bin\Debug\zd.dll 二.随便找个地方新建一个记事本,在记事本中写入以下内容: (command " ...

  9. ajax的使用:(ajaxReturn[ajax的返回方法]),(eval返回字符串);分页;第三方类(page.class.php)如何载入;自动加载函数库(functions);session如何防止跳过登录访问(构造函数说明)

    一.ajax例子:ajaxReturn("ok","eval")->thinkphp中ajax的返回值的方法,返回参数为ok,返回类型为eval(字符串) ...

随机推荐

  1. JVM CPU占满问题定位

    RASP加载后出现JVM CPU占满问题,jstack -F输出信息无法找到对应占用CPU的线程 perf定位到占用CPU的热代码位于Dependencies::find_finalizable_su ...

  2. WinlogonHack获取系统密码

    实验环境: win03 sp1 Gina.dll与Msgina.dll Gina.dll在NT/2000中交互式的登陆支持是由WinLogon调用Gina.dll实现的,Gina.dll提供了一个交互 ...

  3. 2018-2019-2 20162318《网络攻防技术》Exp5 MSF基础应用

    1.实验内容 1.一个主动攻击实践,如ms08_067 2. 一个针对浏览器的攻击,如ms11_050) 3. 一个针对客户端的攻击,如Adobe 4. 成功应用任何一个辅助模块 2.基础问题回答 2 ...

  4. [BJOI2010]次小生成树

    OJ题号: BZOJ1977.COGS2453 题目大意: 给你一个无向连通图,求严格次小生成树. 思路: 对于一般次小生成树,我们有一个结论:一般次小生成树一定可以通过替换掉最小生成树某一条边得到. ...

  5. .net mvc控制器传递方法到视图

    很多人都是在视图里面定义方法,然后再使用.我个人也是这么干的.但是为了验证是否可以将方法从控制器传递到视图,所以做了个测试.结果真的可以.原理是利用了委托(delegate),因为委托本身就是一种类型 ...

  6. DOM-XML(解析与创建)

    /** * 读取(解析)xml文件 * @author Administrator * */ public class DOMRead { public static void main(String ...

  7. 模拟拖拽图片 碰撞检测 DOM 鼠标事件 闭包

    <!doctype html><html lang="en"> <head> <meta charset="UTF-8" ...

  8. [JAVA] JAVA JDK 安装配置

    JDK 安装 下载安装 下载JDK 从oracle官方网站下载并安装JDK. 下载使用文档 从oracle官方网站下载使用帮助文档. 安装库源文件 源文件位于安装目录的 /Library/Java/J ...

  9. Android证书有效性验证方案

    1.前言: 1.1.SSL劫持攻击:          目前虽然很多Android APP使用了https通信方式,但是只是简单的调用而已,并未对SSL证书有效性做验证.在攻击者看来,这种漏洞让htt ...

  10. android aapt 用法 -- ApkReader

    aapt 是android assert packaging tool的缩写,具体如下: 1. 列出apk包的内容 aapt l[ist] [-v] [-a] file.{zip,jar,apk} - ...