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环境下会检测:分隔的目录。