我怀疑这个问题源于对c ++的误解,但是因为我使用Rcpp,我已经标记了这个问题。我创建了两个函数,每个函数都在一个单独的.cpp文件中。
f1.cpp:
// [[Rcpp::depends(RcppProgress)]]
#include <progress.hpp>
using namespace Rcpp;
// [[Rcpp::export]]
NumericVector f1(int n)
{
int i;
Progress p(n, true);
NumericVector x(n);
for( i = 0 ; i < n ; i++ )
{
if (Progress::check_abort() )
Rcpp::stop("Operation cancelled by interrupt.");
p.increment(); // update progress
x[i] = Rf_rnorm(0,1);
}
return x;
}
f2.cpp:
// [[Rcpp::depends(RcppProgress)]]
#include <progress.hpp>
using namespace Rcpp;
// [[Rcpp::export]]
NumericVector f2(int n)
{
int i;
Progress p(n, true);
NumericVector x(n);
for( i = 0 ; i < n ; i++ )
{
if (Progress::check_abort() )
Rcpp::stop("Operation cancelled by interrupt.");
p.increment(); // update progress
x[i] = Rf_rgamma(1,1);
}
return x;
}
他们都依赖于RcppProgress。当我只使用其中一个文件编译我的包时,我没有问题。但是当我用两者编译时,我得到链接器错误:
duplicate symbol __Z14checkInterruptv in:
f1.o
f2.o
duplicate symbol __ZN8Progress18_monitor_singletonE in:
f1.o
f2.o
ld: 2 duplicate symbols for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
我认为这意味着我需要将#include <progress.hpp>
放在一个单独的头文件中,以便从每个cpp文件中包含这些文件,但我已经尝试过了,但没有运气。我还使用Rcpp / RcppProgress查看了其他软件包,但是我应该更改的内容并不明显。
答案 0 :(得分:8)
这不是你的错。这是RcppProgress作者的错。他们的progress.hpp
有
class Progress {
// ...
private: // ===== INSTANCE VARIABLES
static InterruptableProgressMonitor* _monitor_singleton;
};
InterruptableProgressMonitor* Progress::_monitor_singleton = 0; // <-- this defines _monitor_singleton
同样,间接包含的interrupts.hpp
包含
bool checkInterrupt() {
return (R_ToplevelExec(chkIntFn, NULL) == FALSE);
}
当您将标头包含在两个单独的翻译单元(即.cpp
文件)中时,两者都会导致一个定义规则违规,表现为您获得的链接器错误。要解决此问题,您需要以某种方式重新排列代码,以便只有一个.cpp
文件包含progress.hpp
(例如,将两个文件合并为一个文件),或对其进行一些编辑头文件。