Hello, this is my first time writing C code that interacts with R. To make my C code more modular, reusable, and easier to test with unittests, I split my code into: a) code that does stuff b) code that interfaces between a) and R. Only the b) imports the R headers, a) is completely independent of R (and potentially shared between different projects). That brings me to a problem: How to do error handling in C without the use of various C-specific print functions R-specific print functions? The C-specific print functions raise a CRAN note: Compiled code should not call entry points which might terminate R nor write to stdout/stderr instead of to the console, nor use Fortran I/O nor system RNGs But R(C) print functions cannot be used without importing particular header, which would induce otherwise another dependency, and tie it closely with R. This is my first time writing into mailing list, hopefully I am doing everything ok. Thanks everyone! -- Jirka
[R-pkg-devel] Error checking in an independent C code and printing (perror, printf, etc.)
5 messages · Steven Scott, Duncan Murdoch, Ivan Krylov +1 more
All software engineering problems are solved by an additional layer of indirection! ;-) Introduce a function called "process_error". Include one implementation for your standalone C library. Include another R-specific one when using your C library as part of an R package. On Tue, Sep 6, 2022 at 9:23 AM Ji?? Moravec <jiri.c.moravec at gmail.com> wrote:
Hello, this is my first time writing C code that interacts with R. To make my C code more modular, reusable, and easier to test with unittests, I split my code into: a) code that does stuff b) code that interfaces between a) and R. Only the b) imports the R headers, a) is completely independent of R (and potentially shared between different projects). That brings me to a problem: How to do error handling in C without the use of various C-specific print functions R-specific print functions? The C-specific print functions raise a CRAN note: Compiled code should not call entry points which might terminate R nor write to stdout/stderr instead of to the console, nor use Fortran I/O nor system RNGs But R(C) print functions cannot be used without importing particular header, which would induce otherwise another dependency, and tie it closely with R. This is my first time writing into mailing list, hopefully I am doing everything ok. Thanks everyone! -- Jirka
______________________________________________ R-package-devel at r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-package-devel
On 05/09/2022 10:48 p.m., Ji?? Moravec wrote:
Hello, this is my first time writing C code that interacts with R. To make my C code more modular, reusable, and easier to test with unittests, I split my code into: a) code that does stuff b) code that interfaces between a) and R. Only the b) imports the R headers, a) is completely independent of R (and potentially shared between different projects). That brings me to a problem: How to do error handling in C without the use of various C-specific print functions R-specific print functions? The C-specific print functions raise a CRAN note: Compiled code should not call entry points which might terminate R nor write to stdout/stderr instead of to the console, nor use Fortran I/O nor system RNGs But R(C) print functions cannot be used without importing particular header, which would induce otherwise another dependency, and tie it closely with R.
I think the best way is to think of error reporting as part of the interface. Your code that does stuff shouldn't try to print anything, it should just return special error code values to indicate problems. The code in b) looks for those error codes and creates R messages or errors. If you use the a) code in a different project, it would do the same, but report the errors in whatever way is natural in that context.
This is my first time writing into mailing list, hopefully I am doing everything ok.
Looks fine to me! Duncan Murdoch
Hello Ji?? and welcome to the mailing list! On Tue, 6 Sep 2022 14:48:02 +1200
"Ji?? Moravec" <jiri.c.moravec at gmail.com> wrote:
That brings me to a problem: How to do error handling in C without the use of various <...> R-specific print functions?
(Assuming that's what you meant...) One way would be to introduce callbacks from the R-independent part to the R-interfacing part, but I can imagine this to require tedious boilerplate. Also, many of R's entry points can raise an error condition (e.g. if an allocation fails), which would result in a longjmp() away from your code. Any resource not known to R's garbage collector is going to be leaked in this situation. I think you're actually allowed to format strings using sprintf and friends; only actual printing to stdout/stderr is disallowed because the user may be using e.g. Rgui on Windows and not see it at all. If you need to print error messages, you can pass them to the R side as strings, probably in storage allocated by the caller to avoid leaks on errors. Error codes are of course an option too, but can be less informative if not accompanied by an explanation of what went wrong. (It's considered polite for package code to use R's message system not only because of the stdout/Rgui problem mentioned above, but also because it gives the user an option to run your code with suppressMessages() and disable the verbose output. When the R code directly calls cat() or the C code prints directly to console, that option disappears.) To summarise, R would accept any option where only R is interacting with the user (or doing other I/O). If neither of this is satisfying, can you provide a bit more details on the kind of error handling you're looking for?
This is my first time writing into mailing list, hopefully I am doing everything ok.
Indeed you are!
Best regards, Ivan
I was hoping that you will tell me that R takes control of the C's stderr and stdout. That would make stuff easier. But I guess that is not really possible. I went the way suggested before and created an enum of error codes and a (static) const char* array of error messages. When reading about error checking in C, that looked like the most wholesome way. First time using the dreadful "goto", looks like it makes sense to free resources. (https://stackoverflow.com/a/59221452/4868692) It still looks a bit ugly compared to simple "throw" (i.e., too much code noise), and I now understand where the Java's checked exceptions are coming from. And somehow, now that I am thinking about it, I am getting used to it. Thanks again. I hope I am responding correctly ("respond all") and not spamming people. ps.: The .Call interface is easier than it seems, the R documentation is not very good and spread the information a bit too much over many pages. Once I got my .Call(c_hello_world) (including all the linking, info about the C_ naming and speed, the `tools::package_native_routine_registration_skeleton` was nice), it all went quite nicely from there. Particularly, when to use PROTECT() is not clear (new SEXP objects, but not required if they are just interfaced with INTEGER(), REAL() or VECTOR_ELT). The overview: https://stat.ethz.ch/pipermail/r-devel/attachments/20120323/a13f948a/attachment.pdf was also really helpful and should be IMHO part of official documentation. An example how to work with named list (e.g., an S3 class), where subsetting is done by name and not by position, would be really useful. -- Jirka
On 9/7/22 04:52, Ivan Krylov wrote:
Hello Ji?? and welcome to the mailing list! On Tue, 6 Sep 2022 14:48:02 +1200 "Ji?? Moravec" <jiri.c.moravec at gmail.com> wrote:
That brings me to a problem: How to do error handling in C without the use of various <...> R-specific print functions?
(Assuming that's what you meant...) One way would be to introduce callbacks from the R-independent part to the R-interfacing part, but I can imagine this to require tedious boilerplate. Also, many of R's entry points can raise an error condition (e.g. if an allocation fails), which would result in a longjmp() away from your code. Any resource not known to R's garbage collector is going to be leaked in this situation. I think you're actually allowed to format strings using sprintf and friends; only actual printing to stdout/stderr is disallowed because the user may be using e.g. Rgui on Windows and not see it at all. If you need to print error messages, you can pass them to the R side as strings, probably in storage allocated by the caller to avoid leaks on errors. Error codes are of course an option too, but can be less informative if not accompanied by an explanation of what went wrong. (It's considered polite for package code to use R's message system not only because of the stdout/Rgui problem mentioned above, but also because it gives the user an option to run your code with suppressMessages() and disable the verbose output. When the R code directly calls cat() or the C code prints directly to console, that option disappears.) To summarise, R would accept any option where only R is interacting with the user (or doing other I/O). If neither of this is satisfying, can you provide a bit more details on the kind of error handling you're looking for?
This is my first time writing into mailing list, hopefully I am doing everything ok.
Indeed you are!