Discussion:
[Rcpp-devel] Question regarding new pacakge registration requirements
Avraham Adler
2017-03-30 19:55:31 UTC
Permalink
With the changes to requested form of package registration, I want to
ensure that my packages comply. One of them, lamW [1], uses
Rcpp—actually RcppParallel. When looking through the source created by
Rcpp, I can find the RRegisterCallable calls in RcppExports.src.
However, I cannot find any reference to R_registerRoutines or
R_useDynamicSymbols. Do I have to add those manually? If so, do I add
them asa regards the functions *I* wrote in lamw.cpp or as regards the
function wrappers that Rcpp wrote and the .R files call in
RcppExports.R?

Thank you,

Avi

[1] https://bitbucket.org/aadler/lamw
Tim Keitt
2017-03-30 20:06:30 UTC
Permalink
Post by Avraham Adler
If so, do I add
them asa regards the functions *I* wrote in lamw.cpp or as regards the
function wrappers that Rcpp wrote and the .R files call in
RcppExports.R?
I'm a bit confused about this as well. My impression is that the only
reason to register functions is so that *other* packages can call them. If
you do not want to make them available, you don't need to register them. Or
I could have that complete wrong.

THK

If you don't want to register anything, this snippet placed in init.c will
get you past CRAN checks currently:

#include <R.h>
#include <Rinternals.h>
#include <R_ext/Rdynload.h>
R_CallMethodDef callMethods[] = {{NULL, NULL, 0}};
R_CMethodDef cMethods[] = {{NULL, NULL, 0}};
void
R_init_myLib(DllInfo *info)
{
R_registerRoutines(info, cMethods, callMethods, NULL, NULL);
R_useDynamicSymbols(info, FALSE);
}
http://www.keittlab.org/
Avraham Adler
2017-03-30 20:10:57 UTC
Permalink
Post by Tim Keitt
Post by Avraham Adler
If so, do I add
them asa regards the functions *I* wrote in lamw.cpp or as regards the
function wrappers that Rcpp wrote and the .R files call in
RcppExports.R?
I'm a bit confused about this as well. My impression is that the only
reason to register functions is so that *other* packages can call them. If
you do not want to make them available, you don't need to register them. Or
I could have that complete wrong.
THK
If you don't want to register anything, this snippet placed in init.c will
#include <R.h>
#include <Rinternals.h>
#include <R_ext/Rdynload.h>
R_CallMethodDef callMethods[] = {{NULL, NULL, 0}};
R_CMethodDef cMethods[] = {{NULL, NULL, 0}};
void
R_init_myLib(DllInfo *info)
{
R_registerRoutines(info, cMethods, callMethods, NULL, NULL);
R_useDynamicSymbols(info, FALSE);
}
http://www.keittlab.org/
Hello, Tim.

Thank you for the quick response. However, there are three packages which
import the package, and one which links to it [1], which is why I have
Rcpp-created headers in the /inst/include directory [2]. I do not want to
do anything which jeopardizes the downstream users but I do want to be in
compliance.

Thanks,

Avi


[1] https://cran.r-project.org/web/packages/lamW/index.html
[2]
https://bitbucket.org/aadler/lamw/src/a3f5b043872b1761dd5140d77216842fcc3adad7/inst/include/
Dirk Eddelbuettel
2017-03-30 20:29:31 UTC
Permalink
On 30 March 2017 at 15:06, Tim Keitt wrote:
| If you don't want to register anything, this snippet placed in init.c will get
| you past CRAN checks currently:

Boooh. Please accomodate the latter and the spirit of the law, if you can. I
have done so with every package I uploaded in the last few weeks--easily more
than half a dozen.

And it so happens that I made this very topic the inaugural post in what may
become an irregular series of blog posts which I am calling 'R^4'.

See

http://dirk.eddelbuettel.com/blog/2017/03/29#001_easy_package_registration
http://dirk.eddelbuettel.com/blog/2017/03/27#000_introducing_r4

It really is just a single call to a single function in R-devel.

Dirk
--
http://dirk.eddelbuettel.com | @eddelbuettel | ***@debian.org
Tim Keitt
2017-03-30 20:35:56 UTC
Permalink
Post by Dirk Eddelbuettel
Please accomodate the latter and the spirit of the law,
But if you don't intend to export functions to others, then is it correct
to not register them? Or is there a reason for to register anyway? That was
my point of confusion.

"Easy" is quite relative to the amount of time you have to commit.
Docker/rocker/etc/etc/ is not a quick and easy solution. Will Rcpp do this
for us in the future? (Please!)

THK

http://www.keittlab.org/
Dirk Eddelbuettel
2017-03-30 21:00:33 UTC
Permalink
On 30 March 2017 at 15:35, Tim Keitt wrote:
|
| On Thu, Mar 30, 2017 at 3:29 PM, Dirk Eddelbuettel <***@debian.org> wrote:
|
| Please accomodate the latter and the spirit of the law,
|
| But if you don't intend to export functions to others, then is it correct to
| not register them? Or is there a reason for to register anyway? That was my
| point of confusion.

Nope -- please re-read the February post by Brian Ripley which my blog post
also references. Plenty of very good reason to register. (For exporting to
other package you also need to provide a header.)

| "Easy" is quite relative to the amount of time you have to commit. Docker/
| rocker/etc/etc/ is not a quick and easy solution. Will Rcpp do this for us in
| the future? (Please!)

The function creating the src/init.c file was already written by Brian Ripley
and Kurt Hornik.

Dirk
--
http://dirk.eddelbuettel.com | @eddelbuettel | ***@debian.org
Tim Keitt
2017-03-31 02:15:47 UTC
Permalink
http://www.keittlab.org/
Post by Dirk Eddelbuettel
The function creating the src/init.c file was already written by Brian Ripley
and Kurt Hornik.
Here's another:

contents = readLines("src/RcppExports.cpp")
protos = grep("^RcppExport", contents, value = TRUE)
funcs = sub("^RcppExport SEXP (.*)\\(.*", "\\1", protos)
nargs = sapply(gregexpr("\\<SEXP\\>", protos), length) - 1
gen_call_method = function(fname, nargs)
{
if (is.na(fname) || is.na(nargs))
return("\t{NULL, NULL, 0}};")
return(paste0('\t{"', fname, '", (DL_FUNC) &',
fname, ', ', nargs, '}'))
}
funcs = c(funcs, NA); nargs = c(nargs, NA)
cms = lapply(1:length(funcs), function(i) gen_call_method(funcs[i],
nargs[i]))

cat("#include <R.h>\n", file = "src/init.c")
cat("#include <Rinternals.h>\n", file = "src/init.c", append = TRUE)
cat("#include <R_ext/Rdynload.h>\n\n", file = "src/init.c", append = TRUE)

protos = paste0("\n\t*", funcs[-length(funcs)], collapse = ",")
cat(paste0("extern void ", protos, ";\n\n"), file = "src/init.c", append =
TRUE)

cat("R_CallMethodDef callMethods[] = {\n", file = "src/init.c", append =
TRUE)
cat(paste(cms, collapse = ",\n"), file = "src/init.c", append = TRUE)
cat("\n\nvoid\nR_init_myLib(DllInfo *info)\n{\n", file = "src/init.c",
append = TRUE)
cat("\tR_registerRoutines(info, NULL, callMethods, NULL, NULL);\n", file =
"src/init.c", append = TRUE)
cat("\tR_useDynamicSymbols(info, FALSE);\n}", file = "src/init.c", append =
TRUE)

I added it to my 'configure' script.

THK
Post by Dirk Eddelbuettel
Dirk
--
Tim Keitt
2017-03-31 02:58:43 UTC
Permalink
I made a few tweaks. Seems to work so far.

https://github.com/thk686/odeintr/blob/master/src/gen_init_c.R

http://www.keittlab.org/

Loading...