EDIT: If you're going to be doing things with GRIB files I would recommend the GDAL library which is backed by the Open Source Geospatial Foundation. You will save yourself a lot of headache :)
I'm using Qt creator in Ubuntu creating a c++ app. I am attempting to use an external lib, libgrib2c.a, that has a header grib2.h. Everything compiles, but when it tries to link I get the error:
undefined reference to 'seekgb(_IO_FILE*, long, long, long*, long*)
I have tried wrapping the header file with:
extern "C"{
#include "grib2.h"
}
But it didn't fix anything so I figured that was not my problem. In the .pro file I have the line:
include($${ROOT}/Shared/common/commonLibs.pri)
and in commonLibs.pri I have:
INCLUDEPATH+=$${ROOT}/external_libs/g2clib/include
LIBS+=-L$${ROOT}/external_libs/g2clib/lib
LIBS+=-lgrib2c
I am not encountering an error finding the library. If I do a nm command on the libgrib2c.a I get:
nm libgrib2c.a | grep seekgb
seekgb.o:
00000000 T seekgb
And when I run qmake with the additional argument of LIBS+=-Wl,--verbose I can find the lib file in the output:
attempt to open /usr/lib/libgrib2c.so failed
attempt to open /usr/lib/libgrib2c.a failed
attempt to open /mnt/sdb1/ESMF/App/ESMF_App/../external_libs/linux/qwt_6.0.2/lib/libgrib2c.so failed
attempt to open /mnt/sdb1/ESMF/App/ESMF_App/../external_libs/linux/qwt_6.0.2/lib/libgrib2c.a failed
attempt to open ..//Shared/Config/lib/libgrib2c.so failed
attempt to open ..//Shared/Config/lib/libgrib2c.a failed
attempt to open ..//external_libs/libssh2/lib/libgrib2c.so failed
attempt to open ..//external_libs/libssh2/lib/libgrib2c.a failed
attempt to open ..//external_libs/openssl/lib/libgrib2c.so failed
attempt to open ..//external_libs/openssl/lib/libgrib2c.a failed
attempt to open ..//external_libs/g2clib/lib/libgrib2c.so failed
attempt to open ..//external_libs/g2clib/lib/libgrib2c.a succeeded
Although it doesn't show any of the .o files in the library is this because it is a c library in my c++ app?
in the .cpp file that I am trying to use the library I have:
#include "gribreader.h"
#include <stdio.h>
#include <stdlib.h>
#include <external_libs/g2clib/include/grib2.h>
#include <Shared/logging/Logger.hpp>
//------------------------------------------------------------------------------
/// Opens a GRIB file from disk.
///
/// This function opens the grib file and searches through it for how many GRIB
/// messages are contained as well as their starting locations.
///
/// \param a_filePath. The path to the file to be opened.
/// \return True if successful, false if not.
//------------------------------------------------------------------------------
bool GRIBReader::OpenGRIB(std::string a_filePath)
{
LOG(notification)<<"Attempting to open grib file: "<< a_filePath;
if(isOpen())
{
CloseGRIB();
}
m_filePath = a_filePath;
m_filePtr = fopen(a_filePath.c_str(), "r");
if(m_filePtr == NULL)
{
LOG(error)<<"Unable to open file: " << a_filePath;
return false;
}
LOG(notification)<<"Successfully opened GRIB file";
g2int currentMessageSize(1);
g2int seekPosition(0);
g2int lengthToBeginningOfGrib(0);
g2int seekLength(32000);
int i(0);
int iterationLimit(300);
m_GRIBMessageLocations.clear();
m_GRIBMessageSizes.clear();
while(i < iterationLimit)
{
seekgb(m_filePtr, seekPosition, seekLength,
&lengthToBeginningOfGrib, ¤tMessageSize);
if(currentMessageSize != 0)
{
LOG(verbose) << "Adding GRIB message location " << lengthToBeginningOfGrib
<< " with length " << currentMessageSize;
m_GRIBMessageLocations.push_back(lengthToBeginningOfGrib);
m_GRIBMessageSizes.push_back(currentMessageSize);
seekPosition = lengthToBeginningOfGrib + currentMessageSize;
LOG(verbose) << "GRIB seek position moved to " << seekPosition;
}
else
{
LOG(notification)<<"End of GRIB file found, after "<< i
<< " GRIB messages.";
break;
}
}
if(i >= iterationLimit)
{
LOG(warning) << "The iteration limit of " << iterationLimit
<< "was reached while searching for GRIB messages";
}
return true;
}
And the header grib2.h is as follows:
#ifndef _grib2_H
#define _grib2_H
#include<stdio.h>
#define G2_VERSION "g2clib-1.4.0"
#ifdef __64BIT__
typedef int g2int;
typedef unsigned int g2intu;
#else
typedef long g2int;
typedef unsigned long g2intu;
#endif
typedef float g2float;
struct gtemplate {
g2int type; /* 3=Grid Defintion Template. */
/* 4=Product Defintion Template. */
/* 5=Data Representation Template. */
g2int num; /* template number. */
g2int maplen; /* number of entries in the static part */
/* of the template. */
g2int *map; /* num of octets of each entry in the */
/* static part of the template. */
g2int needext; /* indicates whether or not the template needs */
/* to be extended. */
g2int extlen; /* number of entries in the template extension. */
g2int *ext; /* num of octets of each entry in the extension */
/* part of the template. */
};
typedef struct gtemplate gtemplate;
struct gribfield {
g2int version,discipline;
g2int *idsect;
g2int idsectlen;
unsigned char *local;
g2int locallen;
g2int ifldnum;
g2int griddef,ngrdpts;
g2int numoct_opt,interp_opt,num_opt;
g2int *list_opt;
g2int igdtnum,igdtlen;
g2int *igdtmpl;
g2int ipdtnum,ipdtlen;
g2int *ipdtmpl;
g2int num_coord;
g2float *coord_list;
g2int ndpts,idrtnum,idrtlen;
g2int *idrtmpl;
g2int unpacked;
g2int expanded;
g2int ibmap;
g2int *bmap;
g2float *fld;
};
typedef struct gribfield gribfield;
/* Prototypes for unpacking API */
void seekgb(FILE *,g2int ,g2int ,g2int *,g2int *);
g2int g2_info(unsigned char *,g2int *,g2int *,g2int *,g2int *);
g2int g2_getfld(unsigned char *,g2int ,g2int ,g2int ,gribfield **);
void g2_free(gribfield *);
/* Prototypes for packing API */
g2int g2_create(unsigned char *,g2int *,g2int *);
g2int g2_addlocal(unsigned char *,unsigned char *,g2int );
g2int g2_addgrid(unsigned char *,g2int *,g2int *,g2int *,g2int );
g2int g2_addfield(unsigned char *,g2int ,g2int *,
g2float *,g2int ,g2int ,g2int *,
g2float *,g2int ,g2int ,g2int *);
g2int g2_gribend(unsigned char *);
/* Prototypes for supporting routines */
extern double int_power(double, g2int );
extern void mkieee(g2float *,g2int *,g2int);
void rdieee(g2int *,g2float *,g2int );
extern gtemplate *getpdstemplate(g2int);
extern gtemplate *extpdstemplate(g2int,g2int *);
extern gtemplate *getdrstemplate(g2int);
extern gtemplate *extdrstemplate(g2int,g2int *);
extern gtemplate *getgridtemplate(g2int);
extern gtemplate *extgridtemplate(g2int,g2int *);
extern void simpack(g2float *,g2int,g2int *,unsigned char *,g2int *);
extern void compack(g2float *,g2int,g2int,g2int *,unsigned char *,g2int *);
void misspack(g2float *,g2int ,g2int ,g2int *, unsigned char *, g2int *);
void gbit(unsigned char *,g2int *,g2int ,g2int );
void sbit(unsigned char *,g2int *,g2int ,g2int );
void gbits(unsigned char *,g2int *,g2int ,g2int ,g2int ,g2int );
void sbits(unsigned char *,g2int *,g2int ,g2int ,g2int ,g2int );
int pack_gp(g2int *, g2int *, g2int *,
g2int *, g2int *, g2int *, g2int *, g2int *,
g2int *, g2int *, g2int *, g2int *,
g2int *, g2int *, g2int *, g2int *, g2int *,
g2int *, g2int *, g2int *);
#endif /* _grib2_H */
I have been scratching my head for two days on this. If anyone has an idea on what to do or can point me in some sort of direction, I'm stumped. Also, if you have any comments on how I can improve this post I'd love to hear them, kinda new at this posting thing. Usually I'm able to find an answer in the vast stores of knowledge already contained on the web.