c - 带有 .c 和 .cpp 文件的 R 包,带有 Rcpp
问题描述
我正在尝试使用 Rcpp 包作为依赖项构建一个 R 包,其中包含 C(以 .c 文件的形式)和 C++ 代码(以 .cpp 文件的形式)。
我有一些问题。
- 首先,真的有可能做到这一点吗?可以调用同一个 R 包中的 C 脚本和 C++ 脚本吗?
- 如果前一个是可能的,那么如何在 C 和 C++ 脚本中正确注册函数。
为了解决这个问题,我在我的 GitHub 页面 ( https://github.com/tpbilton/testrcpp ) 上设置了一个小示例。我曾经Rcpp.package.skeleton("testrcpp")
初始化包并添加了一些功能(来自本教程https://cran.r-project.org/web/packages/Rcpp/vignettes/Rcpp-introduction.pdf),然后运行Rcpp::compileAttributes()
. 我安装了软件包,c++ 函数convolve_cpp
工作正常,但convolve_c
没有注册,我不知道如何正确执行此操作,我尝试注册这两个函数的尝试无济于事。
解决方案
首先,真的有可能做到这一点吗?可以调用同一个 R 包中的 C 脚本和 C++ 脚本吗?
是的。Rcpp非常有名地利用了R的C API。(参见编写 R 扩展 的第 1.6.4 节可移植 C 和 C++ 代码。
如果前一个是可能的,那么如何在 C 和 C++ 脚本中正确注册函数。
理想情况下,只有C++脚本的表面方面。否则,你会被卡住写胶水。
我采用了这种方法。这篇文章继续详细介绍了细微的变化。可以在非现场找到一个工作示例:
https://github.com/r-pkg-examples/rcpp-and-c
简而言之,我们将为函数定义创建一个头文件并将其包含在C代码中。从那里,我们将创建第三个C++文件,并使用 _Rcpp将该函数导出到R中。
convolve_in_c.h
在这里,我们使用包含保护,#ifndef
并#define
确保如果我们多次重用头文件,函数定义不会重复。
#ifndef CONVOLVE_C_H
#define CONVOLVE_C_H
SEXP convolve_c(SEXP a, SEXP b);
#endif /* CONVOLVE_C_H */
convolve_in_c.c
现在,让我们修改文件以允许我们的自定义标题。
#include <R.h>
#include <Rinternals.h>
// Incorporate our header
#include "convolve_in_c.h"
SEXP convolve_c(SEXP a, SEXP b) {
int na, nb, nab;
double *xa, *xb, *xab;
SEXP ab;
a = PROTECT(coerceVector(a, REALSXP));
b = PROTECT(coerceVector(b, REALSXP));
na = length(a); nb = length(b);
nab = na + nb - 1;
ab = PROTECT(allocVector(REALSXP, nab));
xa = REAL(a); xb = REAL(b); xab = REAL(ab);
for(int i = 0; i < nab; i++)
xab[i] = 0.0;
for(int i = 0; i < na; i++)
for(int j = 0; j < nb; j++)
xab[i + j] += xa[i] * xb[j];
UNPROTECT(3);
return ab;
}
convolve_from_c_to_rcpp.cpp
最后,我们在C++文件中使用C代码,使 C ++中的函数名称与C链接保持一致。此外,我们将数据类型从 操作到。extern
SEXP
NumericVector
#include "Rcpp.h"
// Define the method signature
#ifdef __cplusplus
extern "C" {
#endif
#include "convolve_in_c.h"
#ifdef __cplusplus
}
#endif
//' Call C function from Rcpp
//'
//' Uses the convolve_c function inside of a C++ routine by Rcpp.
//'
//' @param a,b A `numeric` vector.
//'
//' @return
//' A `numeric` vector of length \eqn{N_a + N_b}.
//'
//' @examples
//'
//' convolve_from_c(1:5, 5:1)
//'
//' @export
// [[Rcpp::export]]
Rcpp::NumericVector convolve_from_c(const Rcpp::NumericVector& a,
const Rcpp::NumericVector& b) {
// Compute the result in _C_ from _C++_.
SEXP ab = convolve_c(a, b);
// Cast as an _Rcpp_ NumericVector
Rcpp::NumericVector result( ab );
// Alternatively:
// Rcpp::NumericVector result( convolve_c(a, b) );
// Return result
return result;
}
推荐阅读
- r - 使用 Mantel 测试通过 R 中的距离计算隔离度
- reactjs - 使用 setState 反应不重新渲染组件
- excel - 我需要遍历 24 列并将 countif 用于 6 个不同的标准,其中值位于另一个工作表上的 6 个不同单元格中
- javascript - 如何访问axios实例的baseURL
- excel - 需要找到一个序列公式根据固定值连续减少2个值
- android - Android警报对话框故障
- installation - WIX 引导程序 UI 标题栏颜色更改
- c# - 将抽象类型转换为 7 种可能的其他类型
- overriding - 如何在 Micronaut 应用程序的测试中从 Run on StartupEvent 覆盖 OnApplicationEvent 方法
- c++ - AVFormatContext 错误:我无法获取 AVFormatContext