-
Notifications
You must be signed in to change notification settings - Fork 9
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 our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Saving compiled code from cfunction objects in user defined locations is not supported #13
Comments
A reproducible example showing the bug, slightly adapted from man/utilites.Rd:
which gives
|
Hm, can you not create a local helper that picks the created artifact, here an object file, up and stores it where you want it? [ AFAIK Also, the pair of |
Yes, sure, I could solve this in my package. The more I think about it, the more I think a path argument for cfunction would be the way to go, to have the object stored in a user defined location right away. Then, readDynLib and writeDynLib would not be necessary as far as I can see. knitr chunk dependencies in conjunction with caching are nice, but not if objects contain references to /tmp/xyz. |
Yes, it sounds like |
Meanwhile I tried both approaches... One problem with
After writing using the specified name "testname", we find the two new files in the specified location, next to the three files originally created by
We can read the DLL from these files, but the object still contains references to the original locations.
Only the DLL attribute is modified.
This confirms yesterdays idea that it would be better to allow |
Instead of the argument "file", there are now two arguments "bname" and "directory" (see updated documentation in man/utilities.Rd). However, we still have remainders of the old DLL locations and names in after writing and reading, see eddelbuettel#13.
OK, as I am unlikely to change
I think this works, but needs some testing. @karlines would you like to check if this is what you intended with these functions? You can see the changes I made here. @eddelbuettel I will send a PR when I am confident that everything is OK. |
Looks like you are heading in a fruitful direction of generalizing what we currently, but don't rush a PR -- we have found that more discussion often has value. And it would be good to hear from @karlines first, |
Even after modification of the environment, the finalizer set for the environment of the CFunc function object Is it important to unlink the DLL in the finalizer as done here |
Now I modified the finalizer to unlink only the original DLL that is intended to be temporary ( The code of cfunction was a bit confusing for me, as the variable The current state of the full patch can be seen here. |
I had glanced at your changes earlier (albeit only superficially). Any chance you could make the change to the |
Mhm, yes, I reverted to |
Note however that the functions do not work as they are on the master branch, see the original bug report. So I do not think anyone could have used them. |
I added some tests based on the examples in man/cfunction.Rd. They run fine when run in a normal R session, but compiling fails when these tests are run via R CMD check:
@eddelbuettel Do you have an idea what's going wrong here? |
I do not. I only see the CRAN checks which are all OK. Don't rock the boat :) |
That said, I am of course on board adding unit tests. But if were to decide to do that, I think we would want a different issue ticket for it, and I would likely make a case for tinytest, or for just scripts in |
i know you don't like testthat, don't worry. I just have a script in |
I suspect that is just the usual dance |
Instead of the argument "file", there are now two arguments "bname" and "directory" (see updated documentation in man/utilities.Rd). However, we still have remainders of the old DLL locations and names in after writing and reading, see eddelbuettel#13.
* Overhaul readDynLib and writeDynLib Instead of the argument "file", there are now two arguments "bname" and "directory" (see updated documentation in man/utilities.Rd). However, we still have remainders of the old DLL locations and names in after writing and reading, see #13. * writeDynLib: Also adapt the environment of the function * Export writeDynLib and readDynLib * Test the reloaded CFunc object * dyn.unload is unnecessary, as we have a new dllname * Prevent removal of DLL in finalizer, clean up cfunction and R/utilities.R: - use DLLpath instead of DLLname if it is a path cfunction: - Add 'name' argument to make it possible to specify a function name that is used in the source code of the function - In the finalizer, remove only 'libLFile_orig' which always points to the original DLL file, while 'libLFile' can be changed by 'writeDynLib' to a user defined location R/utilities.R (writeDynLib and readDynLib): - Do not use additional attributes for DLL path, DLL name and function name, but only modify this information in the function environment in 'writeDynLib', and restore this information in 'readDynLib' - Remove code that was meant to support 'CFuncList' objects in 'writeDynLib' and 'readDynLib' * Revert to using a 'file' argument instead of 'bname' Based on #13 (comment) * Add tests and fix bugs that turned up Unfortunately compiling cfunction objects does not work in the R testing environment. The error message upon compiling the first cfunction in tests/cfunction.R: ``` * checking tests ... Running ‘cfunction.R’ ERROR Running the tests in ‘tests/cfunction.R’ failed. Last 13 lines of output: 4: DOUBLE PRECISION x(*) 5: 6: integer i 7: do 1 i=1, n(1) 8: 1 x(i) = x(i)**3 9: 10: RETURN 11: END 12: Compilation ERROR, function(s)/method(s) not created! Error in compileCode(f, code, language, verbose) : Error in file(filename, "r", encoding = encoding) : cannot open the connectionCalls: local ... eval.parent -> eval -> eval -> eval -> eval -> source -> fileIn addition: Warning message:In file(filename, "r", encoding = encoding) : cannot open file 'startup.Rs': No such file or directoryExecution halted Calls: cfunction -> compileCode Execution halted ``` * Overhaul readDynLib and writeDynLib Instead of the argument "file", there are now two arguments "bname" and "directory" (see updated documentation in man/utilities.Rd). However, we still have remainders of the old DLL locations and names in after writing and reading, see #13. * writeDynLib: Also adapt the environment of the function * Export writeDynLib and readDynLib * Test the reloaded CFunc object * dyn.unload is unnecessary, as we have a new dllname * Prevent removal of DLL in finalizer, clean up cfunction and R/utilities.R: - use DLLpath instead of DLLname if it is a path cfunction: - Add 'name' argument to make it possible to specify a function name that is used in the source code of the function - In the finalizer, remove only 'libLFile_orig' which always points to the original DLL file, while 'libLFile' can be changed by 'writeDynLib' to a user defined location R/utilities.R (writeDynLib and readDynLib): - Do not use additional attributes for DLL path, DLL name and function name, but only modify this information in the function environment in 'writeDynLib', and restore this information in 'readDynLib' - Remove code that was meant to support 'CFuncList' objects in 'writeDynLib' and 'readDynLib' * Revert to using a 'file' argument instead of 'bname' Based on #13 (comment) * Add tests and fix bugs that turned up Unfortunately compiling cfunction objects does not work in the R testing environment. The error message upon compiling the first cfunction in tests/cfunction.R: ``` * checking tests ... Running ‘cfunction.R’ ERROR Running the tests in ‘tests/cfunction.R’ failed. Last 13 lines of output: 4: DOUBLE PRECISION x(*) 5: 6: integer i 7: do 1 i=1, n(1) 8: 1 x(i) = x(i)**3 9: 10: RETURN 11: END 12: Compilation ERROR, function(s)/method(s) not created! Error in compileCode(f, code, language, verbose) : Error in file(filename, "r", encoding = encoding) : cannot open the connectionCalls: local ... eval.parent -> eval -> eval -> eval -> eval -> source -> fileIn addition: Warning message:In file(filename, "r", encoding = encoding) : cannot open file 'startup.Rs': No such file or directoryExecution halted Calls: cfunction -> compileCode Execution halted ``` * Remove superseded test script * Improve doc of name argument * Remove superseded test script again This came back with the merge commit and I didn't notice * Write the CFunc object in two steps By separating the process, it is easier to catch potential errors when moving the DLL around (now done in moveDLL()). Also, the files can get independent file names in this way. Only writing CFunc objects is currently supported. * With current cfunction moveDLL prevents removal of DLL during garbage collection. * Improve docs and testing of the 'name' argument * Small doc improvement.
I frequently generate cfunctions in my mkin package by generating C code from a user specified ODE model definition which is then compiled for fast solutions with deSolve within iterative optimizations. Generally, it is fine to have the compiled code under /tmp, but when I have large knitr documents and specific chunks take a long time to complete I use knitr chunk caching and I get problems with model objects in the knitr cache not finding their compiled code any more. Therefore, I would like to store the shared objects generated by cfunctions in a user defined path, e.g. in the current working directory.
The functions readDynLib and writeDynLib from R/utilities.R would fit the bill, but they are not exported, and the former has a bug making the example code in dontrun fail, even if the functions are found by using
inline:::readDynLib
andinline:::writeDynLib
. An alternative to fixing and exporting these functions would be to add an argument to cfunction, defining a path for the shared object.The text was updated successfully, but these errors were encountered: