Uh oh!
There was an error while loading.Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork219
Register native routines automatically within compileAttributes#694
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.
Already on GitHub?Sign in to your account
Uh oh!
There was an error while loading.Please reload this page.
Conversation
codecov-io commentedMay 16, 2017 • edited
Loading Uh oh!
There was an error while loading.Please reload this page.
edited
Uh oh!
There was an error while loading.Please reload this page.
Codecov Report
@@ Coverage Diff @@## master #694 +/- ##==========================================- Coverage 89.72% 89.52% -0.21%========================================== Files 66 66 Lines 3523 3588 +65 ==========================================+ Hits 3161 3212 +51- Misses 362 376 +14
Continue to review full report at Codecov.
|
kevinushey commentedMay 16, 2017
LGTM! If I understand correctly, this means users can implicitly opt-out of Rcpp native routine registration just by making sure they provide their own call to |
jjallaire commentedMay 16, 2017 via email
Yes, that's right. If they have their own init function then we don'tgenerate any of the registration code.However, even in that case if they do `useDynLib(pkgname, .registration =TRUE)` then we will generate the R wrappers using symbol names rather thancharacter vectors. This should mean that users who prefer or who havebecome accustomed to using the R 3.4 helper function will now get generatedR wrapper functions that correctly bind to the registered routines (i.e.users that had previously been diligently registering all their routines topass CRAN checks were not actually *using* those routines because ourgenerated code in RcppExports.R was still referring to functions viacharacter vector rather than symbol. …On Tue, May 16, 2017 at 12:37 PM, Kevin Ushey ***@***.***> wrote: LGTM! If I understand correctly, this means users can implicitly opt-out of Rcpp native routine registration just by making sure they provide their own call to R_init_<pkg> somewhere; is that right? — You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub <#694 (comment)>, or mute the thread <https://github.com/notifications/unsubscribe-auth/AAGXx9-yxBZ0ZbnARsCCP4uRhC7F2mGlks5r6dDdgaJpZM4NcvyM> . |
kevinushey commentedMay 16, 2017
That sounds like the right behavior to me as well. FWIW from what I understand, the I think in theory the 'old' way we constructed Rcpp exports would still work fine -- it's only when users fail to provide the |
jjallaire commentedMay 16, 2017 via email
Yes, that is my understanding as well. …On Tue, May 16, 2017 at 12:50 PM, Kevin Ushey ***@***.***> wrote: That sounds like the right behavior to me as well. FWIW from what I understand, the R_useDynamicSymbols(dllInfo, FALSE) bit implies the following: .Call("routine", PACKAGE = "package") # okay .Call(routine) # okay given R native routine object called 'routine' .Call("routine") # fail: won't discover routine I think in theory the 'old' way we constructed Rcpp exports would still work fine -- it's only when users fail to provide the PACKAGE = argument will lookup fail. (Of course it's better for us to use the routine wrapper objects directly) — You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub <#694 (comment)>, or mute the thread <https://github.com/notifications/unsubscribe-auth/AAGXx9YwME1PzBfrt57g_ijMAATobyaRks5r6dO7gaJpZM4NcvyM> . |
eddelbuettel commentedMay 16, 2017 • edited
Loading Uh oh!
There was an error while loading.Please reload this page.
edited
Uh oh!
There was an error while loading.Please reload this page.
I am not entirely sure I agree with all of this. For months now, I have been doing two things:
but nothing else. In particular, I did not bother to alter all the "quoted" .Call() uses. I also never overwrote the default I on the boolean in I have the suspicion I am still missing something here. |
jjallaire commentedMay 16, 2017
Yes, that's all correct. You were setting the table properly to use native symbols however compileAttributes wasn't generating code that actually used the symbols. e.g. in my reticulate example as a result of registering the symbols the following was sitting in the reticulate namespace: reticulate:::reticulate_py_is_none However, when calling "py_is_none" the string based version of lookup rather than the symbol based lookup was being used. Net: all of that registration was really just meeting the requirements of CRAN checks but not actually put into use by the package. The |
eddelbuettel commentedMay 16, 2017
I think it is not quite as dire. On one package (anytime, use Rcpp, has FALSE) I hit a "unpleasant many-legged creature" when altering a function signature, running (older) But I think I agree: nicer calls, with thesymbol rather than string, are the real goal. Getting there. This is a huge help. Running an RcppArmadillo test now; wonder how to best test this. Probably need to rebuild a few packages with / without the existing |
jjallaire commentedMay 16, 2017 via email
Yes, R was definitely checking but when it came time to call the functionit was doing string based lookup.I believe Doug Bates actually suggested this feature like a week after wecame out with Rcpp attributes and we said "good idea, we'll do that later"(as it turned out much, much later!). His argument was actually about theperformance benefit of just having the pointer in hand vs. having to lookit up with each call, which I think for a frequently called function wouldindeed add up. …On Tue, May 16, 2017 at 1:27 PM, Dirk Eddelbuettel ***@***.*** > wrote: Net: all of that registration was really just meeting the requirements of CRAN checks but not actually put into use by the package. I think it is not quite as dire. On one package (anytime, use Rcpp, has FALSE) I hit a "unpleasant many-legged creature" when altering a function signature, running (older) compileAtttributes() and still couldn't -- as init.c needed an update for the change number of arguments. So *some* checking was done by R. But I think I agree: nicer calls, with the *symbol* rather than string, are the real goal. Getting there. This is a huge help. Running an RcppArmadillo test now; wonder how to best test this. Probably need to rebuild a few packages with / without the existing init.c. — You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub <#694 (comment)>, or mute the thread <https://github.com/notifications/unsubscribe-auth/AAGXx9mUnFF0vwnl62qQmYURAcZu-Ee6ks5r6dyQgaJpZM4NcvyM> . |
eddelbuettel commentedMay 16, 2017
The performance aspect is nice but the delta seems a little marginal from my reading of WRE. Now, I will admit that I got totally confused a few weeks ago over one aspect I couldn't quite remember the details: we added And should we not now push harder for |
eddelbuettel commentedMay 16, 2017
And/or do you know a package using |
jjallaire commentedMay 16, 2017 via email
I don't know of anyone using Rcpp::interfaces and couldn't find any onGitHub!I think the idea was if someone was e.g. creating a bunch of lower levelfunctions that would be useful for other C/C++ codebases they could dothat. In practice though it doesn't seem like people are doing this. …On Tue, May 16, 2017 at 1:51 PM, Dirk Eddelbuettel ***@***.*** > wrote: And/or do you know a package using Rcpp::interface() to provide C(++) code for another package? — You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub <#694 (comment)>, or mute the thread <https://github.com/notifications/unsubscribe-auth/AAGXx1JKUdwAJQLHy88MmaQmzy-QZ_fqks5r6eI5gaJpZM4NcvyM> . |
eddelbuettel commentedMay 16, 2017
Yeah. I have it in RQuantLib, and "more code got generated" (that I sort-of had forgotten about) but I also do not know of a user package ... (And we now have header-only subset of QuantLib in Quantuccia so it is even more moot.) |
eddelbuettel commentedMay 17, 2017
First real test: "boom". In g++ -Wl,-S -shared -L/usr/lib/R/lib -Wl,-Bsymbolic-functions -Wl,-z,relro -o anytime.so RcppExports.o anytime.o init.o -L/usr/lib/R/lib -lRinit.o: Infunction`R_init_anytime':/home/edd/git/anytime/src/init.c:36: multiple definition of`R_init_anytime'RcppExports.o:/home/edd/git/anytime/src/RcppExports.cpp:136: first defined herecollect2: error: ld returned 1 exit status/usr/share/R/share/make/shlib.mk:6: recipe for target'anytime.so' failedmake: *** [anytime.so] Error 1ERROR: compilation failed for package ‘anytime’* removing ‘/usr/local/lib/R/site-library/anytime’* restoring previous ‘/usr/local/lib/R/site-library/anytime’edd@max:~/git/anytime(feature/numeric_input_change)$ Quick guess: Maybe because patch currently does not scan C files? |
Necessary to discover R_init_pkgname functions defined within .c files (e.g. init.c)
jjallaire commentedMay 17, 2017 via email
Good one and yes that was the problem. Just pushed a fix. …On Wed, May 17, 2017 at 6:46 AM, Dirk Eddelbuettel ***@***.*** > wrote: First real test: "boom". In anytime, I have src/init.c but Rcpp created registration in src/RcppExports.cpp too: g++ -Wl,-S -shared -L/usr/lib/R/lib -Wl,-Bsymbolic-functions -Wl,-z,relro -o anytime.so RcppExports.o anytime.o init.o -L/usr/lib/R/lib -lR init.o: In function `R_init_anytime': /home/edd/git/anytime/src/init.c:36: multiple definition of `R_init_anytime'RcppExports.o:/home/edd/git/anytime/src/RcppExports.cpp:136: first defined herecollect2: error: ld returned 1 exit status/usr/share/R/share/make/shlib.mk:6: recipe for target 'anytime.so' failedmake: *** [anytime.so] Error 1ERROR: compilation failed for package ‘anytime’* removing ‘/usr/local/lib/R/site-library/anytime’* restoring previous ***@***.***:~/git/anytime(feature/numeric_input_change)$ Quick guess: Maybe because patch currently does not scan C files? — You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub <#694 (comment)>, or mute the thread <https://github.com/notifications/unsubscribe-auth/AAGXx7_VmARhhu2FwM8duSTwhUviiZhuks5r6s_9gaJpZM4NcvyM> . |
eddelbuettel commentedMay 17, 2017 • edited
Loading Uh oh!
There was an error while loading.Please reload this page.
edited
Uh oh!
There was an error while loading.Please reload this page.
@jjallaire Actual bug. Using my small-ish / recent-ish RcppQuantuccia package, I removed ~/git/rcppquantuccia(master)$ R CMD INSTALL.* installing to library ‘/usr/local/lib/R/site-library’* installing*source* package ‘RcppQuantuccia’ ...** libsg++ -std=gnu++11 -I/usr/share/R/include -DNDEBUG -I../inst/include/ -I. -I"/usr/local/lib/R/site-library/Rcpp/include" -I"/usr/local/lib/R/site-library/BH/include" -fpic -g -O2 -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2 -g -c RcppExports.cpp -o RcppExports.og++ -std=gnu++11 -I/usr/share/R/include -DNDEBUG -I../inst/include/ -I. -I"/usr/local/lib/R/site-library/Rcpp/include" -I"/usr/local/lib/R/site-library/BH/include" -fpic -g -O2 -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2 -g -c dates.cpp -o dates.og++ -std=gnu++11 -I/usr/share/R/include -DNDEBUG -I../inst/include/ -I. -I"/usr/local/lib/R/site-library/Rcpp/include" -I"/usr/local/lib/R/site-library/BH/include" -fpic -g -O2 -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2 -g -c utils.cpp -o utils.og++ -std=gnu++11 -shared -L/usr/lib/R/lib -Wl,-Bsymbolic-functions -Wl,-z,relro -o RcppQuantuccia.so RcppExports.o dates.o utils.o -L/usr/lib/R/lib -lRinstalling to /usr/local/lib/R/site-library/RcppQuantuccia/libs** R** inst** preparing packagefor lazy loading**help*** installinghelp indices** building package indices** testingif installed package can be loadedError: package or namespace load failedfor‘RcppQuantuccia’in .doLoadActions(where, attach): errorin load action .__A__.1for package RcppQuantuccia: .Call("RcppQuantuccia_RcppExport_registerCCallable", PACKAGE ="RcppQuantuccia"):"RcppQuantuccia_RcppExport_registerCCallable" not availablefor.Call()for package"RcppQuantuccia"Error: loading failedExecution haltedERROR: loading failed* removing ‘/usr/local/lib/R/site-library/RcppQuantuccia’* restoring previous ‘/usr/local/lib/R/site-library/RcppQuantuccia’~/git/rcppquantuccia(master)$ Edit 1: The # Register entry points for exported C++ functionsmethods::setLoadAction(function(ns) { .Call('RcppQuantuccia_RcppExport_registerCCallable',PACKAGE='RcppQuantuccia')}) If I comment that out, all is good. Edit 2: And it is caused by the |
jjallaire commentedMay 17, 2017 via email
Indeed! I think that this mechanism has broken the aforementionedRcpp::interfaces(cpp) which you must be using in this package. I'll fixthis tomorrow AM. …On Wed, May 17, 2017 at 4:21 PM, Dirk Eddelbuettel ***@***.*** > wrote:@jjallaire <https://github.com/jjallaire> Actual bug. Using my small-ish / recent-ish RcppQuantuccia package, I removed src/init.c and called compileAttribute(). The RcppExports where updated, but: ~/git/rcppquantuccia(master)$ R CMD INSTALL .* installing to library ‘/usr/local/lib/R/site-library’* installing *source* package ‘RcppQuantuccia’ ...** libs g++ -std=gnu++11 -I/usr/share/R/include -DNDEBUG -I../inst/include/ -I. -I"/usr/local/lib/R/site-library/Rcpp/include" -I"/usr/local/lib/R/site-library/BH/include" -fpic -g -O2 -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2 -g -c RcppExports.cpp -o RcppExports.o g++ -std=gnu++11 -I/usr/share/R/include -DNDEBUG -I../inst/include/ -I. -I"/usr/local/lib/R/site-library/Rcpp/include" -I"/usr/local/lib/R/site-library/BH/include" -fpic -g -O2 -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2 -g -c dates.cpp -o dates.o g++ -std=gnu++11 -I/usr/share/R/include -DNDEBUG -I../inst/include/ -I. -I"/usr/local/lib/R/site-library/Rcpp/include" -I"/usr/local/lib/R/site-library/BH/include" -fpic -g -O2 -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2 -g -c utils.cpp -o utils.o g++ -std=gnu++11 -shared -L/usr/lib/R/lib -Wl,-Bsymbolic-functions -Wl,-z,relro -o RcppQuantuccia.so RcppExports.o dates.o utils.o -L/usr/lib/R/lib -lR installing to /usr/local/lib/R/site-library/RcppQuantuccia/libs** R** inst** preparing package for lazy loading** help*** installing help indices** building package indices** testing if installed package can be loaded Error: package or namespace load failed for ‘RcppQuantuccia’ in .doLoadActions(where, attach): error in load action .__A__.1 for package RcppQuantuccia: .Call("RcppQuantuccia_RcppExport_registerCCallable", PACKAGE = "RcppQuantuccia"): "RcppQuantuccia_RcppExport_registerCCallable" not available for .Call() for package "RcppQuantuccia" Error: loading failed Execution halted ERROR: loading failed* removing ‘/usr/local/lib/R/site-library/RcppQuantuccia’* restoring previous ‘/usr/local/lib/R/site-library/RcppQuantuccia’~/git/rcppquantuccia(master)$ — You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub <#694 (comment)>, or mute the thread <https://github.com/notifications/unsubscribe-auth/AAGXx5wK6fBL3vhgzKPjIyhb_MeWC2n6ks5r61bOgaJpZM4NcvyM> . |
jjallaire commentedMay 17, 2017
Just pushed a fix (and tested it with RcppQuantuccia). There's one more lingering issue: if users of attributes are combining that with exporting C/C++ functions without attributes then our current code generation won't pick that up. I don't know if that scenario exists as a practical matter but it seems like somewhere in the wild it must. We have a couple different options here:
I think option (1) vs. option (2+3) are about the same amount of work. I probably favor (1). |
eddelbuettel commentedMay 17, 2017
Thanks for the fix, will test. I like 1) and was surprised you didn't go calling it directly. Shall we enable that more generally, or 'just' in the case of exported functions? |
…e to discover and register additional non-Rcpp exported native routines
jjallaire commentedMay 18, 2017
I implemented (1) so this case should now be covered. The reason I didn't have R do all of the code generation is that it generates different code (assumes it's in a .c rather than .cpp file) and we may need to eventually inject additional code into the init function (e.g. imagine a package author wants our generated registration butalso wants to run some code on init, we could scan for the definition of Rcpp_init_pkgname and then call it from R_init_pkgname if it exists). Calling R from this spot within code generation also won't find the definitions in RcppExports.R since they haven't yet been written (i.e. we'd need to always inject them into the generated R code, so easier to just generate our own code in the first place). |
eddelbuettel commentedMay 18, 2017
Ahh. I see now. This should be good to merge then. |
krlmlr commentedMay 31, 2017
Re Rcpp::interfaces: I'm actually using it for plogr (logging) and bindrcpp (creating/populating environments with bindings that call a C++ functiion). |
There are two main components here:
Use the metadata that we already have within
compileAttributesto automatically emit a package init function that registers all exported C++ functions with R viaR_registerRoutines.Note that users have been doing this manually for several months and some packages may already have an init function for other reasons. Consequently, we only do automatic registration if no existing package init function is found.
Registering native functions and calling
useDynLib(foo, .registration = TRUE)is actually not sufficient to have R wrappersbind to the registered routines. To do that we actually need to generate this code:Rather than this code:
Note that we only want to generate the former code when the user has included
.registration = TRUE(otherwise the routines won't be present in the package namespace). As a result, we scan theNAMESPACEfile foruseDynLib(pkgname, .registration = TRUE)and only generate R wrappers of that form if it's found.Relevant documentation fromWriting R Extensions is here:https://cran.r-project.org/doc/manuals/r-release/R-exts.html#Registering-native-routines
Of particular interest is the bit about
R_useDynamicSymbols(info, FALSE). My reading of this is that by calling this you are saying that it still okay to to use this syntax:However,only if the symbol has been registered. This is important for us because we are now going to always pass
FALSEtoR_useDynamicSymbols, and we don't want that to break packages that in turn neglect to pass.registration = TRUEtouseDynLib. Since we register all the Rcpp exported functions they will work using either the character based or symbol based.Calllookup.This branch of the reticulate package demonstrates the change in code generation that occurs:
https://github.com/rstudio/reticulate/compare/feature/register-native-routines
Note that we've changed our
@useDynLibroxygen to:And that we've removed entirely the
init.cppfile previously provided as a stub to pass CRAN tests.