[Rd] Dealing with printf() &c. in third-party library code

Martin Morgan mtmorgan at fhcrc.org
Fri Mar 16 01:48:30 CET 2012

On 03/15/2012 02:24 PM, Jon Clayden wrote:
> Martin,
> Thanks for your reply. I wonder if you'd be willing to post your
> "my_fprintf" function, since I'm struggling to get around needing to
> use the "stdout" and "stderr" symbols completely. This function has
> the right effect...
> void rniftyreg_fprintf (FILE *stream, const char *format, ...)
> {
>     va_list args;
>     va_start(args, format);
>     if (stream == stdout)
>         Rvprintf(format, args);
>     else if (stream == stderr)
>         REvprintf(format, args);
>     else
>         vfprintf(stream, format, args);
>     va_end(args);
> }
> ... but the R CMD check info message still arises because stdout and
> stderr still appear. I'm struggling to see how to get around this
> without doing something really ugly, like casting integers to FILE*
> pointers.

Hi Jon --

My own implementation is like yours, where I still reference stderr / 
stdout. But it seems like the meaningful problem (writing to stderr / 
stdout, which R might have re-directed) has been addressed (except for 
the third branch, in your code above).

> All the best,
> Jon
> On 15 March 2012 05:04, Martin Morgan<mtmorgan at fhcrc.org>  wrote:
>> On 03/14/2012 05:15 AM, Jon Clayden wrote:
>>> Dear all,
>>> I recognise the reason for strongly discouraging use of printf() and
>>> similar C functions in R packages, but I wonder what people do in
>>> practice about third-party code which may be littered with such calls.
>>> I maintain a package (RNiftyReg) which provides an R interface to a
>>> third-party library which contains hundreds of calls to printf(...),
>>> fprintf(stderr,...) and similar. It seems to me that there are several
>>> possible approaches, but all have their issues:
>>> 1. Replace all such calls with equivalent Rprintf() calls, using
>>> compiler preprocessing directives to ensure the library does not
>>> become incompatible with other code. For example,
>>> #ifdef RNIFTYREG
>>> Rprintf(...);
>>> #else
>>> printf(...);
>>> #endif
>>> This will be very time-consuming if there are lots of calls, and also
>>> makes the code very untidy and much harder to update when a new
>>> version of the upstream library is released.
>>> 2. Remove all such calls from the code altogether, or comment them
>>> out. The problem here is that doing this safely is hard, because the
>>> call could be part of an "if" statement or similar. For example,
>>> if (test)
>>>   printf("Something");
>>> do_something_important;
>>> If the middle line here is removed, then the last line becomes
>>> (erroneously) conditioned on the test. Plus, once again, you are
>>> introducing a lot of small changes to the library itself.
>>> 3. Redefine printf to use Rprintf, viz.
>>> #ifdef RNIFTYREG
>>> #include<R.h>
>>> #define printf Rprintf
>>> #endif
>>> This will compile as long as the R function is a drop-in replacement
>>> for the original function, which I believe is true for Rprintf (vs.
>>> printf), but isn't true for Calloc (vs. calloc), for example. And I'm
>>> not sure whether this approach can be used to deal with cases of the
>>> form fprintf(stderr,...), where stderr would need to be redefined.
>>> This approach requires only modest changes to the library itself, but
>>> may be fragile to future changes in R.
>>> Are there any other (better?) alternatives? Any thoughts or advice
>>> would be appreciated.
>> In Makevars, I add -Dfprintf=my_fprintf to the pre-processor flags and then
>> implement my_fprintf in a separate source file. This means that the source
>> code of the 3rd party library is not touched, and there is some scope for
>> re-mapping or otherwise intercepting function arguments. For abort and
>> error, I throw an error that encourages the user to save and quit
>> immediately, though this is far from ideal. I too would be interested in
>> better practices for dealing with this, short of whole-sale modification of
>> the third-party library.
>> Martin
>>> All the best,
>>> Jon
>>> ______________________________________________
>>> R-devel at r-project.org mailing list
>>> https://stat.ethz.ch/mailman/listinfo/r-devel
>> --
>> Computational Biology
>> Fred Hutchinson Cancer Research Center
>> 1100 Fairview Ave. N. PO Box 19024 Seattle, WA 98109
>> Location: M1-B861
>> Telephone: 206 667-2793

Computational Biology
Fred Hutchinson Cancer Research Center
1100 Fairview Ave. N. PO Box 19024 Seattle, WA 98109

Location: M1-B861
Telephone: 206 667-2793

More information about the R-devel mailing list