3

假设我在两个不同的R包中有两个独立的 cpp 代码:(请不要从字面上理解这些示例,这些是我问题的最小版本)。

#include <algorithm>
#include <Eigen/Dense>

using namespace std;
using namespace Eigen;
using Eigen::VectorXf;
using Eigen::VectorXi;
using Eigen::RowVectorXf;

float Fmedian(VectorXf& x){
    const int n=x.rows();
    const int half=(n+1)/2-1;               
    float med;
    std::nth_element(x.data(),x.data()+half,x.data()+x.size()); 
    if((n%2)==1){
        med=x(half);
    } else {
        float tmp0=x(half);
        float tmp1=x.segment(half+1,half-1).minCoeff(); 
        med=0.5*(tmp0+tmp1);
    }
    return med;
}
extern "C"{
    void R_Fastmedian(int* n,float* X,int* fMet){
        MatrixXf xi=Map<VectorXf>(X,*n);        
        float Um=Fmedian(xi);
        *fMet=Um;
    }
}

然后,在另一个文件中,我有:

#include <algorithm>
#include <Eigen/Dense>

using namespace std;
using namespace Eigen;
using Eigen::VectorXf;
using Eigen::VectorXi;
using Eigen::RowVectorXf;

float Fmedian(VectorXf& x){
    const int n=x.rows();
    const int half=(n+1)/2-1;               
    float med;
    std::nth_element(x.data(),x.data()+half,x.data()+x.size()); 
    if((n%2)==1){
        med=x(half);
    } else {
        float tmp0=x(half);
        float tmp1=x.segment(half+1,half-1).minCoeff(); 
        med=0.5*(tmp0+tmp1);
    }
    return med;
}
float Fmad(VectorXf& x,float& med){
    const int n=x.rows();
    const int half=(n+1)/2-1;
    float mad;              
    x-=med;
    x=x.cwiseAbs();
    std::nth_element(x.data(),x.data()+half,x.data()+x.size()); 
    if((n%2)==1){
        mad=x(half);
    } else {
        float tmp0=x(half);
        float tmp1=x.segment(half+1,half-1).minCoeff(); 
        mad=0.5*(tmp0+tmp1);
    }
    return(mad*1.4826);
}
extern "C"{
    void R_Fastmad(int* n,float* X,int* fMet){
        MatrixXf xi=Map<VectorXf>(X,*n);        
        float U1=Fmedian(xi);
            float U2=Fmad(xi,U1);
        *fMet=U2;
    }
}

现在,我想将这两个功能组合在一个包中。当我使用 编译第二个代码R CMD时,我会收到 Fmedian 的错误,大意是该函数已在第一个文件中定义。将这两个文件链接在一起的最直接方法是什么?

4

1 回答 1

3

如果我没看错,Fmedian那么两个文件中的实现完全相同。但编译器实际上并不知道这一点,因为它们可能不同并导致歧义,因此出现错误。要修复它,您应该将两种实现统一为一个。

一种方法是:

// the first file
#include <algorithm>
#include <Eigen/Dense>

using namespace std;
using namespace Eigen;
using Eigen::VectorXf;
using Eigen::VectorXi;
using Eigen::RowVectorXf;

// Forward-declare Fmedian as an external function.
// This means that its definition will be found
// in some other file (C++ translation unit) during compilation.
extern float Fmedian(VectorXf& x);

extern "C" {
    void R_Fastmedian(int* n,float* X,int* fMet){
        MatrixXf xi=Map<VectorXf>(X,*n);        
        float Um=Fmedian(xi);
        *fMet=Um;
    }
}

你的第二个文件保持不变。


另请参阅C++的外部函数,链接器如何知道外部函数的定义在哪里?

于 2013-01-16T10:05:00.020 回答