【问题标题】:stringstream not working with Rcpp on OSX 10.6stringstream 在 OSX 10.6 上无法与 Rcpp 一起使用
【发布时间】:2011-12-12 19:38:46
【问题描述】:

似乎 std::stringstream 不适用于 Rcpp。为了隔离问题,我编写了一个最小程序:

#include <string>
#include <sstream>
#include <Rcpp.h>

float atof(std::string a) {
        std::stringstream ss(a);
        Rf_PrintValue(Rcpp::wrap(a));
        float f;
        Rf_PrintValue(Rcpp::wrap(f));
        ss >> f;
        Rf_PrintValue(Rcpp::wrap(f));
        return (f);
}

RcppExport SEXP tsmall(SEXP sR) {
        std::string sC = Rcpp::as<std::string>(sR);
        return Rcpp::wrap(atof(sC));
}

tsmall 应该只是将字符串转换为浮点数。 Rf_PrintValue 用于调试。现在在 OSX 10.16.7 上的 R 中,我得到了

> dyn.load("min.so")
> a = .Call("tsmall","0.213245")
[1] "0.213245"
[1] 0
[1] 0
> a
[1] 0

在另一台机器(Ubuntu)上,它按预期工作:

> dyn.load("min.so")
> a = .Call("tsmall","0.213245")
[1] "0.213245"
[1] 1.401298e-45
[1] 0.213245
> a
[1] 0.213245

我在 OSX 上尝试了一个小型的普通 C++ 程序,当然使用 stringstream 转换字符串和浮点数效果很好。

在 OSX 上使用的编译器是 MacPorts g++-mp-4.4。

更新: 我在Stringstream not working with doubles when _GLIBCXX_DEBUG enabled 发现了早先提出的关于 stringstream 和 OSX 的问题。但是,当我使用 /usr/bin/g++-4.2 中的默认 gcc-4.2 编译该问题中的测试程序时,我得到了错误,但使用 /opt/local/bin/g++-mp-4.4 编译可以正常工作。

但是,我将 Rcpp 代码编译为

$ PKG_CPPFLAGS=`Rscript -e 'Rcpp:::CxxFlags()'` \
         PKG_LIBS=`Rscript -e 'Rcpp:::LdFlags()'` \
         R CMD SHLIB min.cpp

其中使用了 gcc-4.4:

/opt/local/bin/g++-mp-4.4 -I/opt/local/lib/R/include -I/opt/local/lib/R/include/x86_64 -I/opt/local/lib/R/library/Rcpp/include -I/opt/local/include    -fPIC  -pipe -O2 -m64 -c min.cpp -o min.o
/opt/local/bin/g++-mp-4.4 -dynamiclib -Wl,-headerpad_max_install_names -undefined dynamic_lookup -single_module -multiply_defined suppress -L/opt/local/lib -o min.so min.o /opt/local/lib/R/library/Rcpp/lib/x86_64/libRcpp.a -L/opt/local/lib/R/lib/x86_64 -lR

所以我不确定这是否是同一个问题。

更新 2:https://discussions.apple.com/thread/2166586?threadID=2166586&tstart=0 的讨论之后,我在代码顶部添加了以下内容:

#ifdef GLIBCXXDEBUG
#define GLIBCXX_DEBUGDEFINED "1"
#else
#define GLIBCXX_DEBUGDEFINED "<undefined>"
#endif

并根据@Kerrek 的建议将f 初始化为stof 中的float f=0;(尽管这不会改变任何东西)。

Mac 上的输出还是一样的。

【问题讨论】:

    标签: c++ r osx-snow-leopard stringstream rcpp


    【解决方案1】:

    我不知道 R 或 RCPP,但我敢打赌以下代码会触发未定义的行为:

        float f;
        Rf_PrintValue(Rcpp::wrap(f));
    

    在使用它之前,您永远不会初始化 f,读取未初始化的变量是UB。为了安全起见,请说 float f = 0; 之类的内容。

    【讨论】:

    • 我这样做是为了查看返回值的来源。我可以将其更改为 float f=0; 的初始化浮点值,并且输出保持不变。
    【解决方案2】:

    这对我在 Lion 上使用常规 Xcode 附带的编译器套件非常有效。

    > require(inline)
    Le chargement a nécessité le package : inline
    > require(Rcpp)
    Le chargement a nécessité le package : Rcpp
    Le chargement a nécessité le package : int64
    > 
    > inc <- '
    + float atof(std::string a) {
    +         std::stringstream ss(a);
    +         Rf_PrintValue(Rcpp::wrap(a));
    +         float f = 0. ;
    +         Rf_PrintValue(Rcpp::wrap(f));
    +         ss >> f;
    +         Rf_PrintValue(Rcpp::wrap(f));
    +         return (f);
    + }
    + '
    > 
    > fx <- cxxfunction( signature( sR = "character" ), '
    +     std::string sC = as<std::string>(sR);
    +     return wrap(atof(sC));
    + ', plugin = "Rcpp", includes = inc )
    > fx( "1.2" )
    [1] "1.2"
    [1] 0
    [1] 1.2
    [1] 1.2
    

    你的 R 也是用 gcc 4.4 编译的吗?

    【讨论】:

    • 谢谢!此代码也只返回 0。我不确定 R 编译。我只是用 MacPorts 安装它,我不确定 Macports 是使用 XCode gcc 还是它安装的 gcc。如果有帮助,我可以构建另一个 R 并以任何一种方式对其进行测试。虽然我认为我在 10.6 中引用的可能问题已在 10.7 (Lion) 中修复,但它可能不会显示在您的系统中。
    • 我从cran.r-project.org/bin/macosx 下载了预构建的稳定二进制文件,它运行良好。我猜这个问题只出在 Macports R 上,因为它可能使用了 10.6 的坏 gcc。
    • 也许吧。通常,我尝试通过使用 XCode 提供的编译器等来避免麻烦
    猜你喜欢
    • 2011-02-26
    • 2011-10-05
    • 1970-01-01
    • 1970-01-01
    • 2014-08-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多