GDAL은 플러그인을 사용하여 HDF4, HDF5 및 NetCDF의 버그 수정을 컴파일합니다.
HDF4, HDF5와 NetCDF 세 개를 플러그인으로 컴파일한 후에 몇 가지 문제가 발생할 수 있다. 예를 들어 HDF4와 HDF5의 데이터를 열 수 있지만 안의 하위 데이터 집합을 열 수 없다. 한참을 찾아서야 GDAL의 플러그인 메커니즘이 약간 부족하다는 것을 발견했다(작은 문제).
스스로 연구한 결과 GDAL의 플러그인 메커니즘은 이렇다. 코드를 결합해서 보면 파일 gcore/gdaldriver 관리자에 있다.cpp의 함수 void GDALdriverManager::AutoLoadDrivers()에서 가장 중요한 코드를 다음과 같이 선택합니다.
/* -------------------------------------------------------------------- */
/* Format the ABI version specific subdirectory to look in. */
/* -------------------------------------------------------------------- */
CPLString osABIVersion;
osABIVersion.Printf( "%d.%d", GDAL_VERSION_MAJOR, GDAL_VERSION_MINOR );
/* -------------------------------------------------------------------- */
/* Scan each directory looking for files starting with gdal_ */
/* -------------------------------------------------------------------- */
for( int iDir = 0; iDir < CSLCount(papszSearchPath); iDir++ )
{
char **papszFiles = NULL;
VSIStatBufL sStatBuf;
CPLString osABISpecificDir =
CPLFormFilename( papszSearchPath[iDir], osABIVersion, NULL );
if( VSIStatL( osABISpecificDir, &sStatBuf ) != 0 )
osABISpecificDir = papszSearchPath[iDir];
papszFiles = CPLReadDir( osABISpecificDir );
int nFileCount = CSLCount(papszFiles);
for( int iFile = 0; iFile < nFileCount; iFile++ )
{
char *pszFuncName;
const char *pszFilename;
const char *pszExtension = CPLGetExtension( papszFiles[iFile] );
void *pRegister;
if( !EQUAL(pszExtension,"dll")
&& !EQUAL(pszExtension,"so")
&& !EQUAL(pszExtension,"dylib") )
continue;
if( EQUALN(papszFiles[iFile],"gdal_",strlen("gdal_")) )
{
pszFuncName = (char *) CPLCalloc(strlen(papszFiles[iFile])+20,1);
sprintf( pszFuncName, "GDALRegister_%s",
CPLGetBasename(papszFiles[iFile]) + strlen("gdal_") );
}
else if ( EQUALN(papszFiles[iFile],"ogr_",strlen("ogr_")) )
{
pszFuncName = (char *) CPLCalloc(strlen(papszFiles[iFile])+20,1);
sprintf( pszFuncName, "RegisterOGR%s",
CPLGetBasename(papszFiles[iFile]) + strlen("ogr_") );
}
else
continue;
pszFilename =
CPLFormFilename( osABISpecificDir,
papszFiles[iFile], NULL );
CPLErrorReset();
CPLPushErrorHandler(CPLQuietErrorHandler);
pRegister = CPLGetSymbol( pszFilename, pszFuncName );
CPLPopErrorHandler();
if( pRegister == NULL )
{
CPLString osLastErrorMsg(CPLGetLastErrorMsg());
strcpy( pszFuncName, "GDALRegisterMe" );
pRegister = CPLGetSymbol( pszFilename, pszFuncName );
if( pRegister == NULL )
{
CPLError( CE_Failure, CPLE_AppDefined,
"%s", osLastErrorMsg.c_str() );
}
}
if( pRegister != NULL )
{
CPLDebug( "GDAL", "Auto register %s using %s.",
pszFilename, pszFuncName );
((void (*)()) pRegister)();
}
CPLFree( pszFuncName );
}
CSLDestroy( papszFiles );
}
CSLDestroy( papszSearchPath );
위의 코드를 자세히 분석하면 GDAL이 드라이브를 불러오고 등록할 때 플러그인 이름 안의 gdal 을 볼 수 있습니다XXX 뒤에 있는 문자열 XXX를 뺀 다음 함수 GDALRegisterXXX, 플러그인 dll에서 이 함수 찾기 GDALRegisterXXX 포인터, 찾지 못하면 GDAL RegisterMe 함수를 찾습니다.그리고 이 함수를 호출하여 등록합니다.OGR에 대한 플러그인도 유사합니다.
일반적인 플러그인의 경우 내보낸 함수 중 GDALRegister처음 함수는 하나뿐입니다. 플러그인에 GDAL Register가 두 개 있으면함수, 그럼 큰일이다. 플러그인은 플러그인 이름과 같은 하나만 등록할 수 있고 다른 하나는 등록하지 않아서 대응하는 데이터도 열리지 않을 것이다.HDF4, HDF5 및 NetCDF가 이러한 예외입니다.HDF4와 HDF5 플러그인에는 2개의 GDAL Register가 포함되어 있습니다함수, 하나는 데이터를 열기 위한 것이고, 다른 하나는 하위 데이터를 열기 위한 것이다. 즉 GDAL RegisterHDF4 및 GDALRegisterHDF4Image 및 GDALRegisterHDF5 및 GDALRegisterHDF5Image.이렇게 되면 플러그인 방식에 있어서 이 두 개의 뒤에 Image가 있는 것은 틀림없이 등록할 수 없을 것이다.
플러그인 등록의 원리를 알면 해결 방법이 있다. 코드를 바꾸고 싶지 않으면 GDAL의 HDF4와 HDF5의 플러그인 dll을 복사해서 이름을 바꾸고 뒤에 Image를 붙이면 된다. 이렇게 하면 가장 간단하지만 같은 dll은 서로 다른 이름으로 양쪽에 존재하기 때문에 기분이 좋지 않다.그럼 두 번째는 원본 코드를 바꾸는 거예요.구체적으로 위의 코드를 수정하고 HDF의 형식이라면 단독으로 판단한 다음에 Image라는 함수를 등록하면 된다(NetCDF에 대해서도 비슷한 문제가 있다).수정된 코드는 다음과 같습니다.
/* -------------------------------------------------------------------- */
/* Format the ABI version specific subdirectory to look in. */
/* -------------------------------------------------------------------- */
CPLString osABIVersion;
osABIVersion.Printf( "%d.%d", GDAL_VERSION_MAJOR, GDAL_VERSION_MINOR );
/* -------------------------------------------------------------------- */
/* Scan each directory looking for files starting with gdal_ */
/* -------------------------------------------------------------------- */
for( int iDir = 0; iDir < CSLCount(papszSearchPath); iDir++ )
{
char **papszFiles = NULL;
VSIStatBufL sStatBuf;
CPLString osABISpecificDir =
CPLFormFilename( papszSearchPath[iDir], osABIVersion, NULL );
if( VSIStatL( osABISpecificDir, &sStatBuf ) != 0 )
osABISpecificDir = papszSearchPath[iDir];
papszFiles = CPLReadDir( osABISpecificDir );
int nFileCount = CSLCount(papszFiles);
for( int iFile = 0; iFile < nFileCount; iFile++ )
{
char *pszFuncName;
const char *pszFilename;
const char *pszExtension = CPLGetExtension( papszFiles[iFile] );
void *pRegister;
if( !EQUAL(pszExtension,"dll")
&& !EQUAL(pszExtension,"so")
&& !EQUAL(pszExtension,"dylib") )
continue;
if( EQUALN(papszFiles[iFile],"gdal_",strlen("gdal_")) )
{
pszFuncName = (char *) CPLCalloc(strlen(papszFiles[iFile])+20,1);
sprintf( pszFuncName, "GDALRegister_%s",
CPLGetBasename(papszFiles[iFile]) + strlen("gdal_") );
}
else if ( EQUALN(papszFiles[iFile],"ogr_",strlen("ogr_")) )
{
pszFuncName = (char *) CPLCalloc(strlen(papszFiles[iFile])+20,1);
sprintf( pszFuncName, "RegisterOGR%s",
CPLGetBasename(papszFiles[iFile]) + strlen("ogr_") );
}
else
continue;
pszFilename =
CPLFormFilename( osABISpecificDir,
papszFiles[iFile], NULL );
CPLErrorReset();
CPLPushErrorHandler(CPLQuietErrorHandler);
pRegister = CPLGetSymbol( pszFilename, pszFuncName );
CPLPopErrorHandler();
if( pRegister == NULL )
{
CPLString osLastErrorMsg(CPLGetLastErrorMsg());
strcpy( pszFuncName, "GDALRegisterMe" );
pRegister = CPLGetSymbol( pszFilename, pszFuncName );
if( pRegister == NULL )
{
CPLError( CE_Failure, CPLE_AppDefined,
"%s", osLastErrorMsg.c_str() );
}
}
if( pRegister != NULL )
{
CPLDebug( "GDAL", "Auto register %s using %s.",
pszFilename, pszFuncName );
((void (*)()) pRegister)();
// dll ,
const char* pszBaseName = CPLGetBasename(papszFiles[iFile]) + 5;
if( EQUAL(pszBaseName, "HDF4") || EQUAL(pszBaseName, "HDF5") )
{
CPLString osLastErrorMsg(CPLGetLastErrorMsg());
sprintf( pszFuncName, "GDALRegister_%sImage",
CPLGetBasename(papszFiles[iFile]) + 5 );
pRegister = CPLGetSymbol( pszFilename, pszFuncName );
if( pRegister == NULL )
{
CPLError( CE_Failure, CPLE_AppDefined,
"%s", osLastErrorMsg.c_str() );
}
CPLDebug( "GDAL", "Auto register %s using %s.",
pszFilename, pszFuncName );
((void (*)()) pRegister)();
}
else if(EQUAL(pszBaseName, "NETCDF"))
{
CPLString osLastErrorMsg(CPLGetLastErrorMsg());
strcpy( pszFuncName, "GDALRegister_GMT" );
pRegister = CPLGetSymbol( pszFilename, pszFuncName );
if( pRegister == NULL )
{
CPLError( CE_Failure, CPLE_AppDefined,
"%s", osLastErrorMsg.c_str() );
}
CPLDebug( "GDAL", "Auto register %s using %s.",
pszFilename, pszFuncName );
((void (*)()) pRegister)();
}
}
CPLFree( pszFuncName );
}
CSLDestroy( papszFiles );
}
CSLDestroy( papszSearchPath );
}
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Mac의 빠른 검색을 위한 플러그인Mac의 표준 기능에는 빠른 검색(Quick Look)이 있습니다. 파일을 선택하고 공백을 누르면 미리 보기를 쉽게 표시할 수 있습니다. 표준이면 텍스트 파일, PDF, 이미지 등을 표시할 수 있습니다. 여기서는 편...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.