在Qt项目中包含Rcpp会导致影响不同包含库的错误



我正在用Qt Creator制作一个静态库,这个库将用于更大的基于GUI的应用程序。我以前使用过Rcpp,但以R为起点,所以将R数据移动到C++函数中可以做一些事情并得到结果,我习惯于使用R studio来做这件事。这一次,我开始了一个Qt项目,我需要一个表来存储一些数据,Rcpp::Dataframe和一些向量类都非常适合这项工作。在我的.cpp源文件中,我有include语句#include <Rcpp.h>,我在网上查看了一下,发现了Qt中使用的Rcpp/RInside库的一个示例,尽管它更多地是关于RInside而不是Rcpp:RInside和Qt

似乎需要在.pro文件中添加一些内容,才能让qmake做正确的事情。我已经在下面的.pro文件中包含了我认为Rcpp所需的内容。我遇到的问题是,在.pro文件中包含Rcpp内容和.cpp文件中包含include语句之前,包含bpp库(您也可以在下面的.pro文件)不会导致编译中出现任何错误或警告。在.pro文件中包含了包含R和Rcpp的语句之后,我收到了许多警告和一个与bpp组件有关的错误,特别是:/local/yrq12edu/local/bpp/dev/include/Bpp/Numeric/NumConstants.h:96: error: expected unqualified-id before numeric constant。还有很多Wunused-parameter消息,同样,其中大多数似乎是从bpp内的文件中混合而来的。这是我第一次不得不处理这样的事情,尽管我读了很多Qt文档,但我仍然是一个非常新鲜的Qt新手。为什么我以前在处理bpp时没有出现错误,但现在我已经尝试将Rcpp包含到我的Qt项目中了,却出现了错误?我应该怎么做才能采取措施来解决这个问题?

#-------------------------------------------------
#
# Project created by QtCreator 2014-09-05T23:27:21
#
#-------------------------------------------------
QT       -= core gui
TARGET = libHybRIDS
TEMPLATE = lib
CONFIG += staticlib
SOURCES += hybridsengine.cpp
HEADERS += hybridsengine.h
INCLUDEPATH += /local/yrq12edu/local/bpp/dev/include
LIBS += -L/local/yrq12edu/local/bpp/dev/lib -lbpp-core
LIBS += -L/local/yrq12edu/local/bpp/dev/lib -lbpp-seq
# Set R home directory
R_HOME =                $$system(R RHOME)
# Set Rcpp include and lib flags.
RCPPINCL =              $$system($$R_HOME/bin/Rscript -e 'Rcpp:::CxxFlags()')
RCPPLIBS =              $$system($$R_HOME/bin/Rscript -e 'Rcpp:::LdFlags()')
# Set R cpp and ld flags. Also for BLAS and LAPACK it uses.
RCPPFLAGS =             $$system($$R_HOME/bin/R CMD config --cppflags)
RLDFLAGS =              $$system($$R_HOME/bin/R CMD config --ldflags)
RBLAS =                 $$system($$R_HOME/bin/R CMD config BLAS_LIBS)
RLAPACK =               $$system($$R_HOME/bin/R CMD config LAPACK_LIBS)
RCPPWARNING =           -Wno-unused-parameter
QMAKE_CXXFLAGS +=       $$RCPPWARNING $$RCPPFLAGS $$RCPPINCL
QMAKE_LFLAGS +=         $$RLDFLAGS $$RBLAS $$RLAPACK $$RCPPLIBS

unix {
    target.path = /usr/lib
    INSTALLS += target
}

编辑:以下建议我使用了RInside/examples/qt中的示例pro文件作为起点-保持语句的顺序:

#-------------------------------------------------
#
# Project created by QtCreator 2014-09-05T23:27:21
#
#-------------------------------------------------
QT       -= core gui
TARGET = libHybRIDS
TEMPLATE = lib
CONFIG += staticlib
SOURCES += hybridsengine.cpp
HEADERS += hybridsengine.h
## comment this out if you need a different version of R,
## and set set R_HOME accordingly as an environment variable
R_HOME =        $$system(R RHOME)
#message("R_HOME is" $$R_HOME)
## include headers and libraries for R
RCPPFLAGS =         $$system($$R_HOME/bin/R CMD config --cppflags)
RLDFLAGS =      $$system($$R_HOME/bin/R CMD config --ldflags)
RBLAS =         $$system($$R_HOME/bin/R CMD config BLAS_LIBS)
RLAPACK =       $$system($$R_HOME/bin/R CMD config LAPACK_LIBS)
## if you need to set an rpath to R itself, also uncomment
RRPATH =        -Wl,-rpath,$$R_HOME/lib
## include headers and libraries for Rcpp interface classes
## note that RCPPLIBS will be empty with Rcpp (>= 0.11.0) and can be omitted
RCPPINCL =      $$system($$R_HOME/bin/Rscript -e "Rcpp:::CxxFlags()")
RCPPLIBS =      $$system($$R_HOME/bin/Rscript -e "Rcpp:::LdFlags()")
## for some reason when building with Qt we get this each time
##   /usr/local/lib/R/site-library/Rcpp/include/Rcpp/module/Module_generated_ctor_signature.h:25: warning: unused parameter ‘classname
## so we turn unused parameter warnings off
## no longer needed with Rcpp 0.9.3 or later
#RCPPWARNING =      -Wno-unused-parameter
## include headers and libraries for RInside embedding classes
RINSIDEINCL =       $$system($$R_HOME/bin/Rscript -e "RInside:::CxxFlags()")
RINSIDELIBS =       $$system($$R_HOME/bin/Rscript -e "RInside:::LdFlags()")
## compiler etc settings used in default make rules
QMAKE_CXXFLAGS +=   $$RCPPWARNING $$RCPPFLAGS $$RCPPINCL $$RINSIDEINCL
QMAKE_LIBS +=           $$RLDFLAGS $$RBLAS $$RLAPACK $$RINSIDELIBS $$RCPPLIBS
## addition clean targets
QMAKE_CLEAN +=      qtdensity Makefile
unix {
    target.path = /usr/lib
    INSTALLS += target
}

在与RInside和Rcpp相关的语句之前或之后放入我的语句以包括bpp库会导致与以前相同的错误。

来自bpp的.h文件的内容是:

#ifndef _NUMCONSTANTS_H_
#define _NUMCONSTANTS_H_
#include <cmath>
#include <limits>
namespace bpp {
  /**
   * @brief this static class contains several useful constant values.
   *
   * This classe uses function in order to avoid the infamous "static initialization order fiasco".
   * C++0x solves this...
   */
  class NumConstants
  {
  public:
    /**
     * @name Golden ratio.
     *
     * The golden ratio, @f$phi@f$ is equal to @f$frac{1+sqrt{5}}{2} = 1.6180339887498948482ldots@f$.
     * We also define @f$R=phi-1@f$ and @f$C = 1 - R@f$.
     * @{
     */
    static double GOLDEN_RATIO_PHI() { return (1. + sqrt(5.)) / 2.; }
    static double GOLDEN_RATIO_R() { return GOLDEN_RATIO_PHI() - 1.; }
    static double GOLDEN_RATIO_C() { return 1. - GOLDEN_RATIO_R(); }
    /** @} */
    static double MEGA() { return 1e6; }
    static double KILO() { return 1e3; }
    static double DECI() { return 1e-1; }
    static double CENTI() { return 1e-2; }
    static double MILLI() { return 1e-3; }
    static double MICRO() { return 1e-6; }
    static double NANO() { return 1e-9; }
    static double PICO() { return 1e-12; }
    static double SMALL() { return 1e-6; }
    static double TINY() { return 1e-12; }
    static double VERY_TINY() { return 1e-20; }
    static double VERY_BIG() { return static_cast<double>(1.7E+23); }
    /**
     * @name Define those constants in case they would not be available in stl/limits.
     *
     * @{
     */
    static double INF() { return std::numeric_limits<double>::has_infinity ? -log(0) : std::numeric_limits<double>::max(); }
    static double PINF() { return std::numeric_limits<double>::has_infinity ? -log(0) : std::numeric_limits<double>::max(); }
    static double MINF() { return std::numeric_limits<double>::has_infinity ? log(0) : std::numeric_limits<double>::min(); }
    static double NaN() { return NAN; }
    /** @} */
    static double PI() { return 3.141593; }
  };
}//end of namespace bpp.
#endif  //_NUMCONSTANTS_H_

这里有一个猜测:在R_ext/Constants.h中,我们有:

trunk/src/include/R_ext/Constants.h
28:#define M_PI 3.141592653589793238462643383279502884197169399375
32:#define PI             M_PI

该宏定义与PI的函数定义冲突。所以你会期望例如

#include <R.h> // pulls in 'R_ext/Constants.h'
#include "Bpp stuff" // definition for function named PI collides with macro

会产生潜在的错误。PI的R宏定义会泄漏到Bpp中,因此在预处理器完成后,这一行:

static double PI() { return 3.141593; }

看起来像

static double 3.141592653589793238462643383279502884197169399375() { return 3.141593; }

编译器只能说"wat"。这就是为什么包含顺序很重要——首先包含Bpp可以避免宏观污染。

似乎可以通过定义#define STRICT_R_HEADERS来避免这种特殊的污染(因为这就是条目所包含的内容)。

相关内容

  • 没有找到相关文章

最新更新