Thanks very much, Dirk. I've got things working now, thanks to your help. Part of my problem was slurring together @export and [[Rcpp::export]].
I really appreciate the help. Dan. > On Mar 3, 2018, at 12:25 PM, Dirk Eddelbuettel <e...@debian.org> wrote: > > > On 3 March 2018 at 15:57, Daniel Kelley wrote: > | Short version: are there any docs on namespace difficulties that might be > | encountered whilst adding C++ to an R project that already uses C? > > In short, yes. > > It has to do with the symbol autogeneration _and registration_ we support > since last year when R changed in that space and made it (essentially) > mandatory to the registration. > > But now you can now run into issues. The easiest way is (personal view here) > to just be explicit: if and when I would now have two symbols like your > trap(), I preemptively declare the C(++) version trap_impl(), keep the '// > [[Rcpp::export]]' so that it is callable but generally do not export it via > NAMESPACE (and hence do document it in Rd). The last two are optional -- you > could just export to R as well and alias in the help page but then users may > get confused. And I then call the trap_impl() function in another R function > trap() which I document. [ That scheme is sometimes easiest for argument > checks etc which are easier in R than in C++, and generally not time > critical. ] > | > | Long version (and I really do apologize for the length). > | > | I am trying to convert some of the C in my biggish package ("oce", 70 kloc R > | and 7 kloc C) from C to C++, because I think that will be easier for users > to > | work with, if they run into trouble and cannot contact me quickly. > | > | The package is pretty old, and although I use roxygen for manpages, I wrote > | NAMESPACE manually; it has > > That's DESCRIPTION, actually. > > | ``` > | LinkingTo: Rcpp > | Imports: Rcpp > | ``` > | > | as I think is required, for using Rcpp. > | > | So far, I'm working with just a single function, named "trap" (for > trapeziodal > | integration), and it starts as below. > | > | ``` > | #include <Rcpp.h> > | using namespace Rcpp; > | > | //' trapezoidal integration > | //' > | //' This is an interface to C++ code. > | //' @param x vector of x values > | //' @param y vector of y values > | //' @param type number indicating type, 0, 1 or 2 > | //' @export > | // [[Rcpp::export]] > | NumericVector trap(NumericVector x, NumericVector y, NumericVector type) > | { > | ``` > | > | Building in Rstudio causes src/RcppExports.cpp to be created as below. > *NOTE: > | there is no created code relating to CallEntries or R_init_oce, both of > which I > | see (the latter analogously) being defined when I make an Rcpp skeleton > | project, and I think this may be close to the heart of the problem.* > | > | ``` > | // Generated by using Rcpp::compileAttributes() -> do not edit by hand > | // Generator token: 10BE3573-1514-4C36-9D1C-5A225CD40393 > | > | #include <Rcpp.h> > | > | using namespace Rcpp; > | > | // trap > | NumericVector trap(NumericVector x, NumericVector y, NumericVector type); > | RcppExport SEXP _oce_trap(SEXP xSEXP, SEXP ySEXP, SEXP typeSEXP) { > | BEGIN_RCPP > | Rcpp::RObject rcpp_result_gen; > | Rcpp::RNGScope rcpp_rngScope_gen; > | Rcpp::traits::input_parameter< NumericVector >::type x(xSEXP); > | Rcpp::traits::input_parameter< NumericVector >::type y(ySEXP); > | Rcpp::traits::input_parameter< NumericVector >::type type(typeSEXP); > | rcpp_result_gen = Rcpp::wrap(trap(x, y, type)); > | return rcpp_result_gen; > | END_RCPP > | } > | ``` > | > | With things established as the above, the package builds without error, and > I can do > | > | ``` > | .Call("_oce_trap", x, y, type) > | ``` > | > | which works fine. > > You would normally not need this as you would get a caller trap() > autogenerated. That may not happen here as you already had one. > > | ``` > | .Call(`_oce_trap`, x, y, type) > | ``` > | (as in the auto-generaged code in R/RcppExports.R) fails with > | > | ``` > | Error: object '_oce_trap' not found > | ``` > | > | Of course, the R code that gets written automatically also fails, because it > | uses `oce_trap`. > | > | The thing is, I am happy to use .Call() and the above would not be a > problem, but there > | is an autogenerated trap() function in R, and it uses the backtick form and > therefore > | devtools::check() gives a NOTE on the package, which I certainly do not > want. > > That is what the Rcpp::exports tag does for you. The alternative is to do as > you do, _manually_ generate the wrapper as you did and to forgo the > autogeneration. I don't usually work this way, and I am not sure if this > does or does not generate the init stib for you. > > In what I describe above, I let R create an trap_impl() R wrapper for me, but > don't export or document that one. > > | Since I noticed that the autogenerated src/RcppExports.cpp > | lacked anything about CallEntries or R_init_oce, I edited my existing > | src/registerDynamicSymbol.c file, in which I had registered symbols for my > | C code. That file now looks like the following. Here, the CallEntries > definition is new, > > There is a safety aspect. If you had a manual one, it will not create a new > one/ automatically which could overwrite yours. > > Often you are better off deleting you old one and letting it autogenerated. > Maybe try that in another branch. > > | as is the extern and also the third argument to R_registerRoutines(), which > was > | NULL when I was just using C. > | > | ``` > | #include <R.h> > | #include <Rinternals.h> > | #include <R_ext/Rdynload.h> > | > | extern SEXP _oce_trap(SEXP, SEXP, SEXP); > | > | static const R_CallMethodDef CallEntries[] = { > | {"_oce_trap", (DL_FUNC) &_oce_trap, 3}, > | {NULL, NULL, 0} > | }; > | > | void R_init_oce(DllInfo* info) { > | R_registerRoutines(info, NULL, CallEntries, NULL, NULL); > | R_useDynamicSymbols(info, TRUE); > | } > | ``` > | > | Well, the above is a sketch of what I think are salient details. I am not > | entirely sure, but it seems to me that `_oce_trap` ought to accessible with > | .Call(). But it's not, and since this backtick notation is used in > | autogenerated R code, I am stuck with devtools::check() NOTEs that worry > | me. > > I don't use devtools. What matters is what R CMD check says. Which may be > the same, I don't know. > > | My guess is that a lot of my setup will be similar to that of projects > using C that are more > | than perhaps 5 years old. I realize that my setup is a bit of a > hodge-podge, docs created > | by roxygen2 but NAMESPACE hand-rolled, so that might make this different > from > | the setup in other packages. > | > | I wonder if anyone else has got into similar difficulties in trying to add > C++ > | to an R project that already uses C. If so, any hints would be greatly > | appreciated! > | > | Again, I'm sorry for the length of this. I hope to have been complete > enough to > | describe the problem, though. > > No worries That was an exceptionally clear (if long) email, you really did > get to the bottom of most if these things, and yes, some of us had similar > transition woes when the registration scheme changed last year. You are very > close. Hopefully my sketches above will get you closer. > > Cheers, 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