用户在 Rcpp 中编写的函数声明 Header/Namespace
Function Declaration in user written Header/Namespace in Rcpp
这个问题实际上是对上一个问题 的跟进。而且我怀疑通过询问它会有更深入的理解。
错误是
unable to load shared object" in "ParallelExample.so'
我想做的是在 R 包中内部调用 Cpp 函数。为此,我编写了一个头文件并将其添加到 src 目录,并在此头文件中定义了一个名称空间。以下代码出现编译错误:
也就是说,我已经找到了解决这个问题的两种方法。
- 在头文件中定义函数,而不仅仅是声明它。
- 在头文件中保留命名空间。
从我对这个主题所做的 cpp 研究来看,在 Rcpp 之外似乎可行且常见(在头文件的命名空间中声明一个函数)。这让我想知道这只是 mac 编译器的问题还是 Rcpp 的一个特性。
首先,cpp文件:
#include <RcppArmadillo.h>
#include "ExampleInternal.h"
// [[Rcpp::export]]
double myfunc(arma::vec vec_in){
int Len = arma::size(vec_in)[0];
return (vec_in[0] +vec_in[1])/Len;
}
二、Cpp:
#include <RcppArmadillo.h>
#include <RcppParallel.h>
#include "ExampleInternal.h"
#include <random>
using namespace RcppParallel;
struct PARALLEL_WORKER : public Worker{
const arma::vec &input;
arma::vec &output;
PARALLEL_WORKER(const arma::vec &input, arma::vec &output) : input(input), output(output) {}
void operator()(std::size_t begin, std::size_t end){
std::mt19937 engine(1);
for( int k = begin; k < end; k ++){
engine.seed(k);
arma::vec index = input;
std::shuffle( index.begin(), index.end(), engine);
output[k] = ExampleInternal::myfunc(index);
}
}
};
// [[Rcpp::export]]
arma::vec Parallelfunc(int Len_in){
arma::vec input = arma::regspace(0, 500);
arma::vec output(Len_in);
PARALLEL_WORKER parallel_woker(input, output);
parallelFor( 0, Len_in, parallel_woker);
return output;
}
最后是一个内部头文件,也在 src 目录中:
#ifndef EXAMPLEINTERNAL_H
#define EXAMPLEINTERNAL_H
#include <RcppArmadillo.h>
#include <Rcpp.h>
namespace ExampleInternal{
double myfunc(arma::vec vec_in);
}
#endif
您声明并调用了一个函数 ExampleInternal::myfunc
,但随后在全局命名空间中定义了一个函数 myfunc
。这不匹配,我很确定您没有显示的其余错误消息表明 ExampleInternal::myfunc
在 so
文件中找不到。
解决方案:在定义函数时使用相同的命名空间:
#include <RcppArmadillo.h>
#include "ExampleInternal.h"
namespace ExampleInternal {
double myfunc(arma::vec vec_in){
int Len = arma::size(vec_in)[0];
return (vec_in[0] +vec_in[1])/Len;
}
}
我也删除了导出函数的注释。顺便说一句,不要同时包含 RcppAramdillo.h
和 Rcpp.h
.
这个问题实际上是对上一个问题
错误是
unable to load shared object" in "ParallelExample.so'
我想做的是在 R 包中内部调用 Cpp 函数。为此,我编写了一个头文件并将其添加到 src 目录,并在此头文件中定义了一个名称空间。以下代码出现编译错误:
也就是说,我已经找到了解决这个问题的两种方法。
- 在头文件中定义函数,而不仅仅是声明它。
- 在头文件中保留命名空间。
从我对这个主题所做的 cpp 研究来看,在 Rcpp 之外似乎可行且常见(在头文件的命名空间中声明一个函数)。这让我想知道这只是 mac 编译器的问题还是 Rcpp 的一个特性。
首先,cpp文件:
#include <RcppArmadillo.h>
#include "ExampleInternal.h"
// [[Rcpp::export]]
double myfunc(arma::vec vec_in){
int Len = arma::size(vec_in)[0];
return (vec_in[0] +vec_in[1])/Len;
}
二、Cpp:
#include <RcppArmadillo.h>
#include <RcppParallel.h>
#include "ExampleInternal.h"
#include <random>
using namespace RcppParallel;
struct PARALLEL_WORKER : public Worker{
const arma::vec &input;
arma::vec &output;
PARALLEL_WORKER(const arma::vec &input, arma::vec &output) : input(input), output(output) {}
void operator()(std::size_t begin, std::size_t end){
std::mt19937 engine(1);
for( int k = begin; k < end; k ++){
engine.seed(k);
arma::vec index = input;
std::shuffle( index.begin(), index.end(), engine);
output[k] = ExampleInternal::myfunc(index);
}
}
};
// [[Rcpp::export]]
arma::vec Parallelfunc(int Len_in){
arma::vec input = arma::regspace(0, 500);
arma::vec output(Len_in);
PARALLEL_WORKER parallel_woker(input, output);
parallelFor( 0, Len_in, parallel_woker);
return output;
}
最后是一个内部头文件,也在 src 目录中:
#ifndef EXAMPLEINTERNAL_H
#define EXAMPLEINTERNAL_H
#include <RcppArmadillo.h>
#include <Rcpp.h>
namespace ExampleInternal{
double myfunc(arma::vec vec_in);
}
#endif
您声明并调用了一个函数 ExampleInternal::myfunc
,但随后在全局命名空间中定义了一个函数 myfunc
。这不匹配,我很确定您没有显示的其余错误消息表明 ExampleInternal::myfunc
在 so
文件中找不到。
解决方案:在定义函数时使用相同的命名空间:
#include <RcppArmadillo.h>
#include "ExampleInternal.h"
namespace ExampleInternal {
double myfunc(arma::vec vec_in){
int Len = arma::size(vec_in)[0];
return (vec_in[0] +vec_in[1])/Len;
}
}
我也删除了导出函数的注释。顺便说一句,不要同时包含 RcppAramdillo.h
和 Rcpp.h
.