3

2 つの異なるパッケージに 2 つの独立した cpp コードがRあるとします。

#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;
    }
}

今、私はこれら 2 つの機能をパッケージにまとめたいと考えています。を使用して 2 番目のコードをコンパイルするとR CMD、この関数が最初のファイルで既に定義されているという Fmedian のエラーが発生します。これら 2 つのファイルをリンクする最も簡単な方法は何ですか?

4

1 に答える 1

3

私が正しく読んでいれば、Fmedian実装は両方のファイルでまったく同じです。しかし、コンパイラは実際にはそれを認識していません。それは、それらが異なり、あいまいさを引き起こす可能性があるため、エラーが発生するためです。これを修正するには、両方の実装を 1 つに統合する必要があります。

これを行う1つの方法は次のとおりです。

// 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;
    }
}

2 番目のファイルは同じままです。


Externing functions in C++も参照してください。リンカーは extern 関数の定義がどこにあるかをどのように認識しますか

于 2013-01-16T10:05:00.020 に答える