Search code examples
rknitrtmb

C++ for TMB but not Rcpp in knitr


I'm writting a document using knitr that includes C++ code. This code is to be used with the R package TMB. I am using a .Rnw document.

My main problem is that I do not know what to specify for the code chunk engine. I have read a few questions about the settings in knitr for non-R language, but my understanding is that only Rcpp is supported in knitr and not simple C++ code. In addition, here I want to compile the C++ code via TMB. In an ideal world, I would like that when I compile the knitr document that .cpp files are created in the working directory, so that TMB can access them afterward. For now however, when I compile the knitr document I get the following warning:

In get_engine(options$engine) : Unknown language engine 'cpp' (must be registered via knit_engines$set()).

Here is a simple example.

\documentclass{article}

\begin{document}

<<setup, include=FALSE>>=
library(knitr)
  @


<<tmbcpp, eval=FALSE, tidy=FALSE, engine='cpp'>>=
#include <TMB.hpp>

template<class Type>
Type objective_function<Type>::operator() ()
{
    DATA_MATRIX(y); 
    PARAMETER(logitGamma); // Autocorrelation

    Type nll = 0.0;

    return nll;
}

@

<<compileTMB, cache=TRUE, results="hide">>=
library(TMB)
compile("tmbcpp.cpp", flags="-Wno-unused-variable")
dyn.load(dynlib("tmbcpp"))
@

\end{document}

Note that here I am not evaluating the C++ code, I thought that would get around problems, but it doesn't appear to be sufficient.

Any help will be greatly appreciated.


Solution

  • I think I found the perfect solution. Using the Rcpp engine as suggested by Ben Bolker and also use a hook to write the code chunk as discussed here and here.

    \documentclass{article}
    \begin{document}
    
    <<setup, include=FALSE>>=
    library(knitr)
    # To write code chunk to the working directory
    knitr::knit_hooks$set(write_chunk = function(before, options, envir) {
        if (before) {
          fileConn <- file(options$label)
          writeLines(options$code, fileConn)
          close(fileConn)
        }
    })
    @
    
    
    <<tmbcpp.cpp, write_chunk=TRUE, eval=FALSE, tidy=FALSE, engine='Rcpp'>>=
    #include <TMB.hpp>
    
    template<class Type>
    Type objective_function<Type>::operator() ()
    {
        DATA_MATRIX(y); 
        PARAMETER(logitGamma); // Autocorrelation
    
        Type nll = 0.0;
    
        return nll;
    }
    
    @
    
    <<compileTMB, cache=TRUE, results="hide">>=
    library(TMB)
    compile("tmbcpp.cpp", flags="-Wno-unused-variable")
    dyn.load(dynlib("tmbcpp"))
    @
    
    \end{document}
    

    This gives no warning or error, as long as you have the highlight package from André Simon installed: http://www.andre-simon.de/. Bonus it saves the file in the working directory, which is then accessible to TMB to compile and load.