ecCodes学习笔记:eccodes无法读取sample文件
目录
Windows下使用 MSVC 编译的 eccodes 在执行 codes_grib_handle_new_from_samples 时返回空指针。代码如下:
string sample_filename = "regular_ll_pl_grib2";
codes_handle* handle = codes_grib_handle_new_from_samples(nullptr, sample_filename.c_str());
故障排查
已设置ECCODES相关的环境变量 ECCODES_DEFINITION_PATH 和 ECCODES_SAMPLES_PATH。
使用Visual Studio跟踪调试,发现问题出在 grib_templates.c 文件的如下函数中:
grib_handle* grib_external_template(grib_context* c,const char* name)
{
const char *base = c->grib_samples_path;
char buffer[1024];
char *p = buffer;
grib_handle *g = NULL;
if(!base) return NULL;
while(*base)
{
if (*base == ':')
{
*p = 0;
g = try_template(c,buffer,name);
if(g) return g;
p = buffer;
base++; /*advance past delimiter*/
}
*p++ = *base++;
}
*p = 0;
return g = try_template(c,buffer,name);
}
其中 c->grib_samples_path 是 ECCODES_SAMPLES_PATH 中设置目录,因为 ECCODES_SAMPLES_PATH 中可以设置多个目录,所以需要循环检测多个目录,是否存在名称为 name 的 sample 文件。问题就出在分解多个目录的代码上
if (*base == ':')
{
//....
}
Linux 中目录以:
分隔,但Windows中:
是目录的一部分,例如sample目录设为D:\smaple_path
,上述代码就会检查下面两个目录:
- D
- \sample_path
当然就无法找到对应的文件。所以需要对该函数进行修改。
修改
编译eccodes时,设置了 WIN32 宏,通过检测该宏可以判断是否是 Windows 环境。所以将 if 语句改为:
#ifdef WIN32
if (*base == ';')
#else
if (*base == ':')
#endif
{
//...
}
这样在Windows环境下会检测以;
分隔的目录,在Linux环境下会检测:
分隔的目录。