On 30 July 2017 at 19:49, Iñaki Úcar wrote: | 2017-07-30 14:15 GMT+02:00 Dirk Eddelbuettel <e...@debian.org>: | > | > On 30 July 2017 at 02:38, Iñaki Úcar wrote: | > | One last question: would you consider adding a cppXPtr() function to | > | Rcpp? It would work as cppFunction(), but it would return a XPtr | > | instead of the function. I have a working example if you are | > | interested. | > | > "Possibly" -- API and functionality extensions are easier than changes; it | > still adds extra documentation and testing. | > | > Can you detail what you are proposing some more, show an example etc pp? | | Of course. RcppDE would be a use case for this (and my simulator, | another one). Currently, the user must provide not only the C++ | function, but also the adapter: a getter that instantiates an XPtr and | pushes it to R space. It is not difficult, but 1) it's not so | immediate nor intuitive, you need to instruct the user about this, and | 2) it's repetitive and a nuisance. | | So my proposal is to automate this. A new cppXPtr() function would | accept a single C++ function, just like cppFunction, but instead of | exporting it, it would: | | - Detect the function signature. This is easy to do with some regexp, | because it should be C-compatible and you won't have to deal with more | complicated stuff like templates, etc. Example: "SEXP foo(int n, | double l) { return rexp(n, l); }" would produce | | - name: foo | - args: (int n, double l) | - retv: SEXP | | - Construct and append a getter. For the example above, | | SEXP getXPtr() { | typedef SEXP (*funcPtr)(int n, double l); | return XPtr<funcPtr>(new funcPtr(&foo)); | } | | - Export the getter, call it, remove the getter from the environment | and return the externalptr. | | An initial implementation, reusing code (omitted) from cppFunction, | would be (please, find attached a complete example): | | cppXPtr <- function(...) { # same args as cppFunction | # get signature | func <- strsplit(code, "[[:space:]]*\\{")[[1]][[1]] | func <- strsplit(func, "[[:space:]]*\\(")[[1]] | args <- func[[2]] | func <- strsplit(func, "[[:space:]]+")[[1]] | name <- func[[length(func)]] | retv <- func[seq_len(length(func)-1)] | | # process depends | # process plugins | # remainder of scaffolding | # prepend scaffolding to code | | # append a getter | code <- paste(c( | code, | "// [[Rcpp::export]]", | "SEXP getXPtr() {", | paste(" typedef", retv, "(*funcPtr)(", args, ";"), | paste(" return XPtr<funcPtr>(new funcPtr(&", name, "));"), | "}"), collapse="\n") | | # print the generated code if we are in verbose mode | # source cpp into specified environment | | # verify that two functions were exported and return the XPtr | if (length(exported$functions) == 0) | stop("No function definition found") | else if (length(exported$functions) > 2) | stop("More than one function definition") | else { | ptr <- env$getXPtr() | rm(list=exported$functions, envir = env) | ptr | } | }
This might be most suitable for an add-on package, at least until all bugs are ironed out. The use case and scope is more limited than for cppFunction(). Dirk -- http://dirk.eddelbuettel.com | @eddelbuettel | e...@debian.org _______________________________________________ Rcpp-devel mailing list Rcpp-devel@lists.r-forge.r-project.org https://lists.r-forge.r-project.org/cgi-bin/mailman/listinfo/rcpp-devel