{"id":19079763,"url":"https://github.com/enchufa2/rcppxptrutils","last_synced_at":"2025-04-30T05:44:35.528Z","repository":{"id":56937010,"uuid":"98894736","full_name":"Enchufa2/RcppXPtrUtils","owner":"Enchufa2","description":"XPtr Add-Ons for 'Rcpp'","archived":false,"fork":false,"pushed_at":"2024-10-08T11:30:34.000Z","size":32,"stargazers_count":19,"open_issues_count":0,"forks_count":1,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-04-30T05:44:08.437Z","etag":null,"topics":["cran","r","rcpp","xptr"],"latest_commit_sha":null,"homepage":"","language":"R","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Enchufa2.png","metadata":{"files":{"readme":"README.Rmd","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-07-31T14:00:33.000Z","updated_at":"2025-03-22T11:05:57.000Z","dependencies_parsed_at":"2022-08-21T07:20:39.727Z","dependency_job_id":null,"html_url":"https://github.com/Enchufa2/RcppXPtrUtils","commit_stats":null,"previous_names":[],"tags_count":3,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Enchufa2%2FRcppXPtrUtils","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Enchufa2%2FRcppXPtrUtils/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Enchufa2%2FRcppXPtrUtils/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Enchufa2%2FRcppXPtrUtils/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Enchufa2","download_url":"https://codeload.github.com/Enchufa2/RcppXPtrUtils/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":251651221,"owners_count":21621702,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cran","r","rcpp","xptr"],"created_at":"2024-11-09T02:15:57.054Z","updated_at":"2025-04-30T05:44:35.439Z","avatar_url":"https://github.com/Enchufa2.png","language":"R","funding_links":[],"categories":[],"sub_categories":[],"readme":"---\noutput: github_document\n---\n\n\u003c!-- README.md is generated from README.Rmd. Please edit that file --\u003e\n\n```{r, echo = FALSE}\nknitr::opts_chunk$set(\n  collapse = TRUE,\n  comment = \"#\u003e\",\n  fig.path = \"README-\"\n)\n```\n\n# RcppXPtrUtils: XPtr Add-Ons for 'Rcpp'\n\n[![Build Status](https://github.com/Enchufa2/RcppXPtrUtils/actions/workflows/build.yml/badge.svg)](https://github.com/Enchufa2/RcppXPtrUtils/actions/workflows/build.yml)\n[![Coverage Status](https://codecov.io/gh/Enchufa2/RcppXPtrUtils/branch/master/graph/badge.svg)](https://app.codecov.io/gh/Enchufa2/RcppXPtrUtils)\n[![CRAN\\_Status\\_Badge](https://www.r-pkg.org/badges/version/RcppXPtrUtils)](https://cran.r-project.org/package=RcppXPtrUtils)\n[![Downloads](https://cranlogs.r-pkg.org/badges/RcppXPtrUtils)](https://cran.r-project.org/package=RcppXPtrUtils)\n\nThe **RcppXPtrUtils** package provides the means to compile user-supplied C++ functions with 'Rcpp' and retrieve an XPtr that can be passed to other C++ components.\n\n## Installation\n\nInstall the release version from CRAN:\n\n```{r, eval=FALSE}\ninstall.packages(\"RcppXPtrUtils\")\n```\n\nThe installation from GitHub can be done with the [remotes](https://cran.r-project.org/package=remotes) package:\n\n```{r, eval=FALSE}\nremotes::install_github(\"Enchufa2/RcppXPtrUtils\")\n```\n\n## Use case\n\nLet's suppose we have a package with a core written in C++, connected to an R API with `Rcpp`. It accepts a user-supplied R function to perform some processing:\n\n```{r, engine='Rcpp', eval=FALSE}\n#include \u003cRcpp.h\u003e\nusing namespace Rcpp;\n\ntemplate \u003ctypename T\u003e\nNumericVector core_processing(T func, double l) {\n  double accum = 0;\n  for (int i=0; i\u003c1e3; i++)\n    accum += sum(as\u003cNumericVector\u003e(func(3, l)));\n  return NumericVector(1, accum);\n}\n\n// [[Rcpp::export]]\nNumericVector execute_r(Function func, double l) {\n  return core_processing\u003cFunction\u003e(func, l);\n}\n```\n\nBut calling R from C++ is slow, so we can think about improving the performance by accepting a compiled function. In order to do this, the core can be easily extended to accept an `XPtr` to a compiled function:\n\n```{r, engine='Rcpp', eval=FALSE}\ntypedef SEXP (*funcPtr)(int, double);\n\n// [[Rcpp::export]]\nNumericVector execute_cpp(SEXP func_, double l) {\n  funcPtr func = *XPtr\u003cfuncPtr\u003e(func_);\n  return core_processing\u003cfuncPtr\u003e(func, l);\n}\n```\n\n```{r, engine='Rcpp', echo=FALSE}\n#include \u003cRcpp.h\u003e\nusing namespace Rcpp;\n\ntemplate \u003ctypename T\u003e\nNumericVector core_processing(T func, double l) {\n  double accum = 0;\n  for (int i=0; i\u003c1e3; i++)\n    accum += sum(as\u003cNumericVector\u003e(func(3, l)));\n  return NumericVector(1, accum);\n}\n\n// [[Rcpp::export]]\nNumericVector execute_r(Function func, double l) {\n  return core_processing\u003cFunction\u003e(func, l);\n}\n\ntypedef SEXP (*funcPtr)(int, double);\n\n// [[Rcpp::export]]\nNumericVector execute_cpp(SEXP func_, double l) {\n  funcPtr func = *XPtr\u003cfuncPtr\u003e(func_);\n  return core_processing\u003cfuncPtr\u003e(func, l);\n}\n```\n\nTo easily leverage this feature, the `RcppXPtrUtils` package provides `cppXPtr()`, which compiles a user-supplied C++ function using `Rcpp::cppFunction()` and returns an `XPtr`:\n\n```{r}\n# compile the code above\n# Rcpp::sourceCpp(code='...')\n\nlibrary(RcppXPtrUtils)\n\nfunc_r \u003c- function(n, l) rexp(n, l)\nfunc_cpp \u003c- cppXPtr(\"SEXP foo(int n, double l) { return rexp(n, l); }\")\n\nmicrobenchmark::microbenchmark(\n  execute_r(func_r, 1.5),\n  execute_cpp(func_cpp, 1.5)\n)\n```\n\nThe object returned by `cppXPtr()` is just an `externalptr` wrapped into an object of class `XPtr`, which stores the signature of the function. If you are a package author, you probably want to re-export `cppXPtr()` and ensure that user-supplied C++ functions comply with the internal signatures in order to avoid runtime errors. This can be done with the `checkXPtr()` function:\n\n```{r, error=TRUE}\nfunc_cpp\ncheckXPtr(func_cpp, \"SEXP\", c(\"int\", \"double\")) # returns silently\ncheckXPtr(func_cpp, \"int\", c(\"int\", \"double\"))\ncheckXPtr(func_cpp, \"SEXP\", c(\"int\"))\ncheckXPtr(func_cpp, \"SEXP\", c(\"double\", \"int\"))\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fenchufa2%2Frcppxptrutils","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fenchufa2%2Frcppxptrutils","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fenchufa2%2Frcppxptrutils/lists"}