First, is it actually possible to do this? Can one call C scripts and C++ scripts that are in the same R package?
Yes. Rcpp very famously is taking advantage of R's C API. (c.f. Section 1.6.4 Portable C and C++ code of Writing R Extensions
.
If the previous is possible, how then does one properly register the functions in the C and C++ scripts.
Ideally, only surface aspects from the C++ script. Otherwise, you're stuck writing the glue.
I've taken this approach. The post goes on to detail the slight changes. A working example can be found off-site at:
https://github.com/r-pkg-examples/rcpp-and-c
In short, we'll create a header file for the function definitions and include it with the C code. From there, we'll create a third file that is in C++ and export that function into R using _Rcpp.
convolve_in_c.h
Here we use an inclusion guard via #ifndef and #define to ensure the function definitions are not repeated if we reuse the header file multiple times.
#ifndef CONVOLVE_C_H
#define CONVOLVE_C_H
SEXP convolve_c(SEXP a, SEXP b);
#endif /* CONVOLVE_C_H */
convolve_in_c.c
Now, let's modify the file to allow for our custom header.
#include <R.h>
#include <Rinternals.h>
// Incorporate our header
#include "convolve_in_c.h"
SEXP convolve_c(SEXP a, SEXP b) {
int na, nb, nab;
double *xa, *xb, *xab;
SEXP ab;
a = PROTECT(coerceVector(a, REALSXP));
b = PROTECT(coerceVector(b, REALSXP));
na = length(a); nb = length(b);
nab = na + nb - 1;
ab = PROTECT(allocVector(REALSXP, nab));
xa = REAL(a); xb = REAL(b); xab = REAL(ab);
for(int i = 0; i < nab; i++)
xab[i] = 0.0;
for(int i = 0; i < na; i++)
for(int j = 0; j < nb; j++)
xab[i + j] += xa[i] * xb[j];
UNPROTECT(3);
return ab;
}
convolve_from_c_to_rcpp.cpp
Finally, we incorporate the C code using extern within our C++ file to have the function name in C++ align with the C linkage. In addition, we manipulate the data type from SEXP to NumericVector.
#include "Rcpp.h"
// Define the method signature
#ifdef __cplusplus
extern "C" {
#endif
#include "convolve_in_c.h"
#ifdef __cplusplus
}
#endif
//' Call C function from Rcpp
//'
//' Uses the convolve_c function inside of a C++ routine by Rcpp.
//'
//' @param a,b A `numeric` vector.
//'
//' @return
//' A `numeric` vector of length \eqn{N_a + N_b}.
//'
//' @examples
//'
//' convolve_from_c(1:5, 5:1)
//'
//' @export
// [[Rcpp::export]]
Rcpp::NumericVector convolve_from_c(const Rcpp::NumericVector& a,
const Rcpp::NumericVector& b) {
// Compute the result in _C_ from _C++_.
SEXP ab = convolve_c(a, b);
// Cast as an _Rcpp_ NumericVector
Rcpp::NumericVector result( ab );
// Alternatively:
// Rcpp::NumericVector result( convolve_c(a, b) );
// Return result
return result;
}