GDAL打开mdb文件失败解决方法(二)

上一篇http://blog.csdn.net/liminlu0314/article/details/53433014博文中说到,可以通过配置项来解决mdb文件打开失败的问题。该问题主要是在64位的程序中会出现。仔细查看gdal的代码,发现在源码中已经针对这个问题进行了修改,但是测试发现修改的不彻底。

具体的bug信息参考http://trac.osgeo.org/gdal/ticket/5594。GDAL库中源码片段如下,详见文件ogrodbcdatasource.cpp中的132行左右,位于函数OGRODBCDataSource::OpenMDB中。

/* -------------------------------------------------------------------- */
/*      Initialize based on the DSN.                                    */
/* -------------------------------------------------------------------- */
    CPLDebug( "ODBC", "EstablishSession(%s)", pszDSN );

    if( !oSession.EstablishSession( pszDSN, NULL, NULL ) )
    {
        int bError = TRUE;
        if( EQUAL(pszDSN, "") )//注释掉这句话即可
        {
            // Trying with another template (#5594)
            pszDSNStringTemplate = "DRIVER=Microsoft Access Driver (*.mdb, *.accdb);DBQ=%s";
            CPLFree( pszDSN );
            pszDSN = (char *) CPLMalloc(strlen(pszNewName)+strlen(pszDSNStringTemplate)+100);
            snprintf( pszDSN,
                      strlen(pszNewName)+strlen(pszDSNStringTemplate)+100,
                      pszDSNStringTemplate,  pszNewName );
            CPLDebug( "ODBC", "EstablishSession(%s)", pszDSN );
            if( oSession.EstablishSession( pszDSN, NULL, NULL ) )
            {
                bError = FALSE;
            }
        }
        if( bError )
        {
            CPLError( CE_Failure, CPLE_AppDefined,
                    "Unable to initialize ODBC connection to DSN for %s,\n"
                    "%s", pszDSN, oSession.GetLastError() );
            CPLFree( pszDSN );
            return FALSE;
        }
    }

上述代码虽然加了匹配另一个模板,但是有个判断if( EQUAL(pszDSN, "") ),这个判断由于pszDSN通过上面的赋值,肯定是有值的,所以这个判断永远为FALSE,也就是if内的代码不会执行,这样就导致修改了其实和没有修改是一样的。所以为了能够在使用第一个模板失败时,使用第二个模板,需要将if这句话注释掉即可。

修改完重新编译即可。

PS:最后又发现了一个问题,在打开调试开关之后,执行会崩溃,通过调试发现位于该文件的218行的 if( oTableList.GetTables() )中执行失败,函数GetTables的源码如下:

int CPLODBCStatement::GetTables( const char *pszCatalog,
                                 const char *pszSchema )

{
    CPLDebug( "ODBC", "CatalogNameL: %s\nSchema name: %s",
		pszCatalog , pszSchema); //这句出问题了

#if (ODBCVER >= 0x0300)

    if( !m_poSession->IsInTransaction() )
    {
        // Commit pending transactions and set to autocommit mode.
        m_poSession->ClearTransaction();
    }

#endif
......

调试发现在调用CPLDebug函数时,传入的两个参数均为NULL导致CPLDebug函数崩溃,此处加一个判断就可以了。如果不启用调试应该也不会出问题。

你可能感兴趣的:(GDAL,C++编程技术,OGR,ODBC,MDB,GDAL交流)