2

I have the following directory structure

my_func
    - my_func_r.cpp
    - my_func.c
    - my_func.h
    - my_func_test.c
    - matrix/
      - matrix.h
      - matrix.c

The matrix directory contains some matrix structures in matrix.h and some initialisation, free, print etc. functions in matrix.c. The my_func.h file is something like

#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include "matrix/matrix.h"

... some structures and templates ...

The my_func.c file is then

#include "my_func.h"

... helper functions ...

int my_func(...) {
    ... my_func stuff ...     
    return 0;
}

The my_func_test.c is something like

#include "my_func.h"

int main() {
    ... some test ...
    return 0;
}

With gcc/g++ I can run this fine with

gcc my_func_test.c my_func.c matrix/matrix.c -o test -lm

The final file my_func_r.cpp is an interface between the Rcpp structures and the structures used in my_func.c. It is currently something like

#include "my_func.h"
#include <Rcpp.h>

// [[Rcpp::export]]
int my_func_r(Rcpp::List x, ...) {
    ... convert inputs to structure recognised by my_func.h ...       
    ... run my_func.c ...
    ... put returned objects back into one of the R structure ...

    return 0;
}

The problem I have is if I now run

sourceCpp('my_func_r.cpp', verbose=TRUE, rebuild=TRUE)

It complains about missing symbols for functions located in matrix/matrix.c. A workaround is to simply paste all my header and source code from both the my_func and matrix files at the top of my_func_r.cpp.

This however feels a very unsatisfactory solution especially for code maintenance. What is the easiest way to accomplish what I am trying to do?

rwolst
  • 12,904
  • 16
  • 54
  • 75

1 Answers1

7

Quick ones:

  1. This is not really particular to Rcpp per se
  2. You are simply struggling with a more advanced / complicated src/ directory in an R build.
  3. There is official documentation about this in Writing R Extensions, and the questions has come up here on SO before.
  4. You could compile a libmatrix.a first in the subdirectory and link to that. This is doable via a simple src/Makevars but still discouraged. So read on.
  5. But this is a self-inflicted wound. Just copy matrix.h and matrix.c into src/, adjust the include path, and you are done.
  6. As always: Create a package. Don't use sourceCpp() on larger setup. It is not made for that,
Dirk Eddelbuettel
  • 360,940
  • 56
  • 644
  • 725
  • So unfortunately I accepted this too soon as I had copied over the `my_func_r.cpp` with all the header and source code at the top, not the original. When I do as you say and move `matrix.h` and `matrix.c` into `src/` when I try to install the package it complains `undefined symbol: _Z17freeIntegerMatrixP13IntegerMatrix`. The `freeIntegerMatrix` function is contained in `matrix.c` so it doesn't seem to be linking correctly. The tests still run fine (after a slight tweak) with the new directory architecture so I don't think this is the issue. – rwolst May 11 '17 at 17:48