1

I have an third party source file and corresponding header (containing the declarations and include directives for GSL etc) which are written in C. I am trying to build an R package around these source files, basically making a wrappers for the functions using Rcpp. Problem is that these files contain restrict qualifier which is not part of the C++ standard, so R CMD INSTALL cannot compile the package. It does use C compiler for .c file, but want's to compile .h file with C++ compiler and it fails. it fails when it finds restrict in header file (which is included in .cpp file).

I am not that familiar with C and compiler things and Rcpp etc, so I am not sure what would be a best approach here?

Easiest thing would probably be to remove the restrict keyword. This is what I have currently done (I am suprised that R CMD INSTALL works when I remove restrict from header file but leave them to .c file). But I rather not alter the .c and .h files as they are also used in non-R environment by others (executable and in Python) and it would be nice to have identical files for all projects.

I also tried to define empty keyword restrict so that it would just "remove" restrict from function definitions if the compilation was done in C++ compiler, but I couldn't get that work. I read about similar approach somewhere but apparently it doesn't work that way.

Would it work if I could somehow tell the compiler (via Makevars or something?) that the particular .h file should be compiled with C compiler? Or is there going to be problems with C++ function calling those functions?

Or will the whole keyword even matter in terms of performance if those functions are called from R via C++ wrapper?

One thing would be to just ditch the Rcpp and use .C instead of .Call from R, but as the performance is a key here, that doesn't feel a good option, as I understand that .Call is faster (and more reliable).

Note that eventually this package could find it's way to CRAN, so the solution should be fairly portable. There seems to be some C++ compiler specific keywords for restrict but I guess those are not an option due to the portability.

Jouni Helske
  • 6,427
  • 29
  • 52
  • When you say defining `restrict` to be empty didn't work, what exactly happened? Also, something I'm confused about: why is Rcpp trying to compile your header files at all? Wouldn't it only need to compile your .c files? – John Zwinck Oct 04 '14 at 07:47
  • Oh yes I miswrote (I'm really a newb with these things...), Rcpp isn't compiling header files but anyway does something with it (as I include it in .cpp file so I can call those functions). Error message I get is "In file included from xR.cpp:3:0: x.h:77:34: error: expected ',' or '...' before 'input'" (I have variable double const* restrict input in functio declaration). – Jouni Helske Oct 04 '14 at 07:59

1 Answers1

3

It sounds like you are making a .cpp file which does #include <x.h> where x.h is a C header which uses restrict. If that's true, I think you can modify your .cpp file to do this:

#define restrict // nothing
extern "C"
{
#include <x.h>
}

Then compilation of your C++ code will not see the restrict keyword, and also I have wrapped the header in extern "C" because if the header itself doesn't do that internally, you need to, in order that your C++ compiler will not apply C++ "name mangling" to the functions declared inside.

John Zwinck
  • 239,568
  • 38
  • 324
  • 436
  • Thank you, that did it. I tried extern "C" without restrict define and other way around but forgot to use them together. What I am still wondering is where does that empty definition affect. I mean what about the restricts in the function definitions in .c file? – Jouni Helske Oct 04 '14 at 11:18
  • Aha, right. So `restrict` in C means "this pointer doesn't alias another one." Since your C++ code now has the restrict keyword removed, it is incumbent upon you (or rather, your Rcpp wrapper function) to make sure you do not pass the same or overlapping pointers as two arguments to the C function. For example if the function is "add" you must not try to do `add(&x, &x)`, but rather make a copy of x into y and do `add(&x, &y)`. Probably this won't be a big deal for you, but maybe you need to check your values before calling C. – John Zwinck Oct 04 '14 at 11:21
  • Yes I understand that but why doesn't the compiler give error that the declaration and the definition differ? Or does that new definition of restrict affect to .c file also? – Jouni Helske Oct 04 '14 at 11:36
  • 1
    The compiler does not know. The restrict keyword doesn't change the function signature, so you can call it with or without that keyword in the declaration. But if you call the function with two aliased pointers, you will have undefined behavior (maybe it will work, maybe it will crash, depends how crazy the optimizer got with the function's implementation). Since there is no function name overloading in C, you could even change the number of parameters in the declaration and the program would still compile, but it might crash etc. C++ is different because mangled names include const etc. – John Zwinck Oct 04 '14 at 13:09