使用 Xptr 和 Function 调用 Rcpp 函数 - 只有 xptr case 有效
Calling Rcpp function with Xptr and Function - only xptr case works
我正在尝试开发一个包,我需要在其中输入来自用户的函数(可以使用 Rcpp
或在 R
中定义),将其发送到另一个函数(在包内) 在 struct
中并在那里进行处理。
当我使用 Rcpp::Xptr
(即函数指针)时,代码有效,但同样不适用于 Rcpp::Function
。为用户使用 Rcpp::Function
的好处是他们可以在 R
中定义函数(尽管会损失很多性能增益)。
首先是有效的:
#include <Rcpp.h>
using namespace Rcpp;
// define the structure
struct xptr_data{
SEXP xptr;
};
// a minimal function (user-defined)
// [[Rcpp::export]]
NumericVector timesTwo(NumericVector x) {
return x * 2;
}
// pointer to function defined
typedef NumericVector (*funcPtr) (NumericVector y);
// [[Rcpp::export]]
XPtr<funcPtr> putFunPtrInXPtr() {
XPtr<funcPtr> rhs_ptr(new funcPtr(×Two), false);
return rhs_ptr;
}
// this function will be in the package
NumericVector call_by_xptr_struct(NumericVector y, void* user_data){
struct xptr_data *my_rhs_ptr = (struct xptr_data*)user_data;
SEXP xpsexp = (*my_rhs_ptr).xptr;
// use function pointer to get the derivatives
XPtr<funcPtr> rhs_xptr(xpsexp);
funcPtr rhs_fun = *rhs_xptr;
// use the function to calculate value of RHS ----
return(rhs_fun(y));
}
// using xptr to evaluate function - this will be exported
// from the package
//[[Rcpp::export]]
NumericVector xptr_call_struct(NumericVector y, SEXP xpsexp){
struct xptr_data my_xptr = {NULL};
my_xptr.xptr = xpsexp;
return call_by_xptr_struct(y, (void*)&my_xptr);
}
/*** R
rhs_ptr <- putFunPtrInXPtr()
xptr_call_struct(c(1,2), rhs_ptr)
[1] 2 4
*/
什么不起作用,
如果函数在R
中定义,而我直接使用Rcpp::Function
,它会导致整个R会话崩溃,
#include <Rcpp.h>
using namespace Rcpp;
// define the function based structure
struct func_data{
Function func;
};
// processes the input function
NumericVector call_by_func_struct(NumericVector y, void* user_data){
struct func_data *my_rhs_fun = (struct func_data*)user_data;
Function func = (*my_rhs_fun).func;
return(func(y));
}
// this will be exported from the package
//[[Rcpp::export]]
NumericVector func_call_struct(NumericVector y, Function func){
struct func_data my_func = {NULL};
my_func.func = func;
return call_by_func_struct(y, (void*)&my_func);
}
/*** R
timesThree <- function(y){
y <- 3 * y
y
}
*/
上面的代码可以正常编译,但是当我调用函数 func_call_struct(c(1,2), timesThree))
时,它会导致整个 R 会话崩溃。
关于 R
为何崩溃以及如何输入 R
中定义的函数的任何指导都将非常有帮助。
此外,是否有任何方法可以传递 Rcpp
中定义的输入函数(例如,上面的 timesTwo
)而不是它们的 Xptr
。我认为在不牺牲 Rcpp
带来的速度的情况下,最终用户的困惑会稍微少一些(因为他们不必生成函数指针)。
如果您 使用可用的 Function
,它会起作用:
[...]
// this will be exported from the package
//[[Rcpp::export]]
NumericVector func_call_struct(NumericVector y, Function func){
struct func_data my_func = {func};
return call_by_func_struct(y, (void*)&my_func);
}
至于你的附加问题:我看不出在不使用外部指针的情况下在 R 中存储 C++ 函数指针的可能性。您不能提供一个从函数指针创建外部指针的辅助函数(可能是 wrap()
)吗?沿着这些线的东西:
#include <Rcpp.h>
using namespace Rcpp;
// define the structure
struct xptr_data{
SEXP xptr;
};
// pointer to function defined
typedef NumericVector (*funcPtr) (NumericVector y);
// this function will be in the package
NumericVector call_by_xptr_struct(NumericVector y, void* user_data){
struct xptr_data *my_rhs_ptr = (struct xptr_data*)user_data;
SEXP xpsexp = (*my_rhs_ptr).xptr;
// use function pointer to get the derivatives
XPtr<funcPtr> rhs_xptr(xpsexp);
funcPtr rhs_fun = *rhs_xptr;
// use the function to calculate value of RHS ----
return(rhs_fun(y));
}
// using xptr to evaluate function - this will be exported
// from the package
//[[Rcpp::export]]
NumericVector xptr_call_struct(NumericVector y, SEXP xpsexp){
struct xptr_data my_xptr = {xpsexp};
return call_by_xptr_struct(y, (void*)&my_xptr);
}
// function in package with only C++ API
XPtr<funcPtr> wrapFunPtr(funcPtr& f) {
XPtr<funcPtr> rhs_ptr(&f, false);
return rhs_ptr;
}
// user-defined functions
NumericVector timesTwo(NumericVector x) {
return x * 2;
}
// [[Rcpp::export]]
XPtr<funcPtr> putFunPtrInXPtr() {
static funcPtr f = ×Two;
return wrapFunPtr(f);
}
/*** R
rhs_ptr <- putFunPtrInXPtr()
xptr_call_struct(c(1,2), rhs_ptr)
*/
用户将提供最后两个函数。使用 C++11,这可以像这样简化:
// [[Rcpp::export]]
XPtr<funcPtr> putFunPtrInXPtr() {
static funcPtr timesTwo{ [](NumericVector x) -> NumericVector { return x * 2; } };
return wrapFunPtr(timesTwo);
}
虽然在这种情况下使用
可能就足够了
// [[Rcpp::export]]
XPtr<funcPtr> putFunPtrInXPtr() {
static funcPtr timesTwo{ [](NumericVector x) -> NumericVector { return x * 2; } };
XPtr<funcPtr> rhs_ptr(timesTwo, false);
return rhs_ptr;
}
不需要 wrapFunPtr
在包中。用户必须提供一个函数,其中包括一些样板代码加上 lambda 表达式中的实际 "meat"。
我正在尝试开发一个包,我需要在其中输入来自用户的函数(可以使用 Rcpp
或在 R
中定义),将其发送到另一个函数(在包内) 在 struct
中并在那里进行处理。
当我使用 Rcpp::Xptr
(即函数指针)时,代码有效,但同样不适用于 Rcpp::Function
。为用户使用 Rcpp::Function
的好处是他们可以在 R
中定义函数(尽管会损失很多性能增益)。
首先是有效的:
#include <Rcpp.h>
using namespace Rcpp;
// define the structure
struct xptr_data{
SEXP xptr;
};
// a minimal function (user-defined)
// [[Rcpp::export]]
NumericVector timesTwo(NumericVector x) {
return x * 2;
}
// pointer to function defined
typedef NumericVector (*funcPtr) (NumericVector y);
// [[Rcpp::export]]
XPtr<funcPtr> putFunPtrInXPtr() {
XPtr<funcPtr> rhs_ptr(new funcPtr(×Two), false);
return rhs_ptr;
}
// this function will be in the package
NumericVector call_by_xptr_struct(NumericVector y, void* user_data){
struct xptr_data *my_rhs_ptr = (struct xptr_data*)user_data;
SEXP xpsexp = (*my_rhs_ptr).xptr;
// use function pointer to get the derivatives
XPtr<funcPtr> rhs_xptr(xpsexp);
funcPtr rhs_fun = *rhs_xptr;
// use the function to calculate value of RHS ----
return(rhs_fun(y));
}
// using xptr to evaluate function - this will be exported
// from the package
//[[Rcpp::export]]
NumericVector xptr_call_struct(NumericVector y, SEXP xpsexp){
struct xptr_data my_xptr = {NULL};
my_xptr.xptr = xpsexp;
return call_by_xptr_struct(y, (void*)&my_xptr);
}
/*** R
rhs_ptr <- putFunPtrInXPtr()
xptr_call_struct(c(1,2), rhs_ptr)
[1] 2 4
*/
什么不起作用,
如果函数在R
中定义,而我直接使用Rcpp::Function
,它会导致整个R会话崩溃,
#include <Rcpp.h>
using namespace Rcpp;
// define the function based structure
struct func_data{
Function func;
};
// processes the input function
NumericVector call_by_func_struct(NumericVector y, void* user_data){
struct func_data *my_rhs_fun = (struct func_data*)user_data;
Function func = (*my_rhs_fun).func;
return(func(y));
}
// this will be exported from the package
//[[Rcpp::export]]
NumericVector func_call_struct(NumericVector y, Function func){
struct func_data my_func = {NULL};
my_func.func = func;
return call_by_func_struct(y, (void*)&my_func);
}
/*** R
timesThree <- function(y){
y <- 3 * y
y
}
*/
上面的代码可以正常编译,但是当我调用函数 func_call_struct(c(1,2), timesThree))
时,它会导致整个 R 会话崩溃。
关于 R
为何崩溃以及如何输入 R
中定义的函数的任何指导都将非常有帮助。
此外,是否有任何方法可以传递 Rcpp
中定义的输入函数(例如,上面的 timesTwo
)而不是它们的 Xptr
。我认为在不牺牲 Rcpp
带来的速度的情况下,最终用户的困惑会稍微少一些(因为他们不必生成函数指针)。
如果您 Function
,它会起作用:
[...]
// this will be exported from the package
//[[Rcpp::export]]
NumericVector func_call_struct(NumericVector y, Function func){
struct func_data my_func = {func};
return call_by_func_struct(y, (void*)&my_func);
}
至于你的附加问题:我看不出在不使用外部指针的情况下在 R 中存储 C++ 函数指针的可能性。您不能提供一个从函数指针创建外部指针的辅助函数(可能是 wrap()
)吗?沿着这些线的东西:
#include <Rcpp.h>
using namespace Rcpp;
// define the structure
struct xptr_data{
SEXP xptr;
};
// pointer to function defined
typedef NumericVector (*funcPtr) (NumericVector y);
// this function will be in the package
NumericVector call_by_xptr_struct(NumericVector y, void* user_data){
struct xptr_data *my_rhs_ptr = (struct xptr_data*)user_data;
SEXP xpsexp = (*my_rhs_ptr).xptr;
// use function pointer to get the derivatives
XPtr<funcPtr> rhs_xptr(xpsexp);
funcPtr rhs_fun = *rhs_xptr;
// use the function to calculate value of RHS ----
return(rhs_fun(y));
}
// using xptr to evaluate function - this will be exported
// from the package
//[[Rcpp::export]]
NumericVector xptr_call_struct(NumericVector y, SEXP xpsexp){
struct xptr_data my_xptr = {xpsexp};
return call_by_xptr_struct(y, (void*)&my_xptr);
}
// function in package with only C++ API
XPtr<funcPtr> wrapFunPtr(funcPtr& f) {
XPtr<funcPtr> rhs_ptr(&f, false);
return rhs_ptr;
}
// user-defined functions
NumericVector timesTwo(NumericVector x) {
return x * 2;
}
// [[Rcpp::export]]
XPtr<funcPtr> putFunPtrInXPtr() {
static funcPtr f = ×Two;
return wrapFunPtr(f);
}
/*** R
rhs_ptr <- putFunPtrInXPtr()
xptr_call_struct(c(1,2), rhs_ptr)
*/
用户将提供最后两个函数。使用 C++11,这可以像这样简化:
// [[Rcpp::export]]
XPtr<funcPtr> putFunPtrInXPtr() {
static funcPtr timesTwo{ [](NumericVector x) -> NumericVector { return x * 2; } };
return wrapFunPtr(timesTwo);
}
虽然在这种情况下使用
可能就足够了// [[Rcpp::export]]
XPtr<funcPtr> putFunPtrInXPtr() {
static funcPtr timesTwo{ [](NumericVector x) -> NumericVector { return x * 2; } };
XPtr<funcPtr> rhs_ptr(timesTwo, false);
return rhs_ptr;
}
不需要 wrapFunPtr
在包中。用户必须提供一个函数,其中包括一些样板代码加上 lambda 表达式中的实际 "meat"。