From mtmorgan at fhcrc.org  Thu Mar 15 06:04:43 2012
From: mtmorgan at fhcrc.org (Martin Morgan)
Date: Wed, 14 Mar 2012 22:04:43 -0700
Subject: [Rd] Dealing with printf() &c. in third-party library code
In-Reply-To: <CAM9CR=2iwS1E3TFnh5y-SRCh5p3KEtSD1ChO7bVpXgMsRV_PrQ@mail.gmail.com>
References: <CAM9CR=2iwS1E3TFnh5y-SRCh5p3KEtSD1ChO7bVpXgMsRV_PrQ@mail.gmail.com>
Message-ID: <4F61786B.6030200@fhcrc.org>

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



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