c++ - 在 C++ 应用程序中使用 libgrib2c,链接器错误 "Undefined reference to..."

标签 c++ qt gcc linker

编辑:如果您要处理 GRIB 文件,我会推荐 GDAL library这是由 Open Source Geospatial Foundation 支持的.你会省去很多麻烦:)

我在 Ubuntu 中使用 Qt creator 创建一个 C++ 应用程序。我正在尝试使用具有 header grib2.h 的外部库 libgrib2c.a。一切都可以编译,但是当它尝试链接时出现错误:

undefined reference to 'seekgb(_IO_FILE*, long, long, long*, long*)

我试过用以下方法包装头文件:

extern "C"{
#include "grib2.h"
}

但它没有解决任何问题,所以我认为这不是我的问题。在 .pro 文件中,我有一行:

include($${ROOT}/Shared/common/commonLibs.pri)

在 commonLibs.pri 中我有:

INCLUDEPATH+=$${ROOT}/external_libs/g2clib/include
LIBS+=-L$${ROOT}/external_libs/g2clib/lib
LIBS+=-lgrib2c

我没有遇到查找库的错误。如果我在 libgrib2c.a 上执行 nm 命令,我会得到:

nm libgrib2c.a | grep seekgb
seekgb.o:
00000000 T seekgb

当我使用附加参数 LIBS+=-Wl,--verbose 运行 qmake 时,我可以在输出中找到 lib 文件:

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

尽管它没有显示库中的任何 .o 文件,这是因为它是我的 C++ 应用程序中的 C 库吗?

在我尝试使用我拥有的库的 .cpp 文件中:

#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, &currentMessageSize);
    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;
}

而头文件grib2.h如下:

#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  */

这两天一直在摸不着头脑。如果有人知道该怎么做或者能给我指出某种方向,我会很困惑。此外,如果您对我如何改进这篇文章有任何意见,我很乐意听取他们的意见,在这篇文章中有点新鲜。通常我能够在网络上已包含的大量知识库中找到答案。

最佳答案

尝试通过将以下内容放在头文件顶部附近来明确指定外部 C 链接:

#ifdef __cplusplus
extern "C" {
#endif

在底部附近:

#ifdef __cplusplus
}
#endif

关于c++ - 在 C++ 应用程序中使用 libgrib2c,链接器错误 "Undefined reference to...",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11767169/

相关文章:

c++ - C 中变量的作用域与生命周期

c++ - 从相对于加载可执行文件的目录加载 .so

c++ - 以基类为值的 std::map 中的继承

gcc - 从 64 位汇编调用 C 函数

c++ - Visual Studio 和 Xcode 中的 C++ 运算符重载错误

c++ - 为什么slot函数调用成功也无法插入文本

c - 从 QT 运行 C 程序

c++11 - 如何避免模板实例化和符号表导致的C++代码膨胀?

c++ - 编译器不会使用 -std=c++11 编译智能指针

wpf - 是否可以将 QT 应用程序托管到 WPF 应用程序中?