如何在头文件中定义Rcpp函数参数默认值并解决R调用报错?
解决Rcpp函数仅在头文件指定默认值的问题
这个问题的核心原因很明确:C头文件里的默认参数只是给C编译器看的,但Rcpp生成R接口的时候,只会读取你标记了// [[Rcpp::export]]的那个函数的签名。你原来的cpp文件里foo(int k)没有默认参数,所以Rcpp生成的R包装函数根本不知道有默认值这回事,自然会报参数缺失的错误。
要实现“仅在头文件定义默认值”的需求,我们可以通过「头文件定义默认值常量+cpp导出函数引用该常量」的方式来实现,具体步骤如下:
1. 修改头文件foo.h
在头文件里,我们把默认值定义为一个常量,同时在函数声明里使用这个常量作为默认参数:
#ifndef foo_H #define foo_H #include <Rcpp.h> // 把默认值统一定义在头文件中,方便后续维护 const int FOO_DEFAULT_K = 3; // 函数声明使用头文件里的常量作为默认参数 int foo(int k = FOO_DEFAULT_K); #endif
2. 修改cpp文件foo.cpp
在cpp的导出函数中,我们同样引用头文件里的常量作为默认参数,这样Rcpp就能识别到这个默认值并生成对应的R接口:
#include "foo.h" #include <Rcpp.h> using namespace Rcpp; //' Some description //' //' @param k An integer (default: 3) //' @export // [[Rcpp::export]] int foo(int k = FOO_DEFAULT_K) { return(k); }
为什么这样能行?
- 头文件里的
FOO_DEFAULT_K是唯一的默认值来源,完全满足你“仅在头文件指定默认值”的要求; - cpp里的导出函数签名带上了默认参数,Rcpp在生成R包装函数时会读取这个信息,给R端的函数也加上对应的默认值;
- 后续如果要修改默认值,只需要改动头文件里的常量即可,不需要修改cpp代码,维护起来更方便。
这样编译R包后,你在R中调用foo()就会正常返回默认值3了。
内容的提问来源于stack exchange,提问作者Bogdan
相关产品推荐
相关产品推荐

