2

I tried to call c++ function from another .cpp file. I used .h header. See below what I did.

I have a f.h file:

#ifndef PACKAGENAME_ADD_H
#define PACKAGENAME_ADD_H

#include <Rcpp.h>
Rcpp::NumericVector f(Rcpp::NumericVector x) ;

#endif

f.cpp file:

#include <Rcpp.h>
using namespace Rcpp;

NumericVector f(NumericVector x) {
  return x * 2;
}

g.cpp file:

#include <Rcpp.h>
#include <f.h>
using namespace Rcpp;
// [[Rcpp::export]]
NumericVector g(NumericVector x) {
  return f(x);
}

The three files are in the same folder I got this error when I run g.cpp:

Rcpp::sourceCpp('~/g.cpp')

Error in dyn.load("/tmp/Rtmpdu4AWp/sourceCpp-x86_64-pc-linux-gnu-0.12.17/sourcecpp_260f5e1a9ebc/sourceCpp_9.so") : unable to load shared object '/tmp/Rtmpdu4AWp/sourceCpp-x86_64-pc-linux-gnu-0.12.17/sourcecpp_260f5e1a9ebc/sourceCpp_9.so': /tmp/Rtmpdu4AWp/sourceCpp-x86_64-pc-linux-gnu-0.12.17/sourcecpp_260f5e1a9ebc/sourceCpp_9.so: undefined symbol: _Z1fN4Rcpp6VectorILi14ENS_15PreserveStorageEEE

Can someone help me? I work on ubuntu 18.04 and I have R 3.4.4 version.

14
  • 5
    Including a header just gives you the declaration of functions - enough for the compiler, not enough for the linker. To actually create an executable you also need to link with the implementation (the object file or library defining the function). The source files being in the same folder is irrelevant. Commented Sep 10, 2018 at 19:38
  • Thanks @JesperJuhl for your reply. Please i am a beginner. Can you explain more? Commented Sep 10, 2018 at 19:45
  • Duplicated? I do not understand Commented Sep 10, 2018 at 19:49
  • 4
    @Ari.stat I would follow the advice often given by Dirk (the creator of Rcpp) and create a package. sourceCpp() wasn't meant for a multiple files. Making R packages that call C++ via Rcpp is simple; look at help("Rcpp::Rcpp.package.skeleton") or the Rcpp package vignette or this answer (disclaimer: mine) with an example of making a package from scratch with C++ & Fortran code Commented Sep 10, 2018 at 19:57
  • 2
    @JesperJuhl All of that is true, but offers little help to those in OP's situation who are compiling C++ code for the purpose of calling it from R, all with the help of the Rcpp R package. As Ralf Stubner mentioned, "in the context of Rcpp, compilation and linking is to some extend automated." Someone calling sourceCpp() from R is coming at this from an entirely different context than you're familiar with. At a certain point, the question marked as dupe and the things you mention could be helpful, but not without understanding how this mixes with R/Rcpp specific issues. Commented Sep 10, 2018 at 20:10

1 Answer 1

3

The way I am most familiar with dealing with this issue in the context of Rcpp is by creating a package. In the case you present in the original post, as pointed out by Ralf Stubner it isn't really necessary; after changing the brackets(<>) around f.h in g.cpp to quotes (""), your code compiled fine for me with sourceCpp():

Rcpp::sourceCpp("g.cpp")
g(1:10)
# [1]  2  4  6  8 10 12 14 16 18 20

(for details see section 1.10 of the Rcpp Attributes vignette).

However, if you are eventually needing multiple .cpp files to compile (i.e., not just one that relies on an implementation in another), the way to go is creating a package. This might sound involved or intimidating, but with the tools provided by Rcpp, it's really quite simple. Here are the steps I took to turn your code into a package:

  1. From R, run Rcpp::Rcpp.package.skeleton("SOanswer", example_code = FALSE)
  2. Delete the file Read-and-delte-me.
  3. Add the C++ files from your original post into the src/ folder (with only one minor edit -- changing the brackets(<>) around f.h in g.cpp to quotes ("")).
  4. From R, run Rcpp::compileAttributes("SOanswer/") and devtools::install("SOanswer/")

Then it should compile nicely and you can run g() from R:

SOanswer::g(1:10)
# [1]  2  4  6  8 10 12 14 16 18 20

I will say that I would add there a step 0: Read the vignettes at https://cran.r-project.org/package=Rcpp, in particular the Rcpp Introduction and Rcpp Package vignettes. You can also check out this lovely example of a package with headers in src/ provided by coatless in the comments.

Sign up to request clarification or add additional context in comments.

5 Comments

To piggyback on @duckmayr's answer, check out github.com/r-pkg-examples/rcpp-headers-src for a package implementation w/ headers in src/
great! when I changed the brackets (<>) around f.h in g.cpp to quotes ("") it works very well. Thanks for your help. Endeed, I want to create a package further but I need the function now for some cheikings. I have somes questions for the package. Shoud I create a sub-folder inst/include/ in my package main folder for .h files or can I put them in scr/ folder ?
@coatless Good resource! I've added it to the answer.
@Ari.stat Either will work, but you'll need to go the inst/include route if you want other R packages to be able to link to your header files. If you want to see examples of R packages that do that, check out these two packages I'm developing on my GitHub: RcppDist (to provide C++ headers for more probability distributions for Rcpp users) and bggum (there I'm not really looking for other packages to link to my header, I just did it that way out of habit)
@Ari.stat Header files for internal functions should go into src. Into inst/include I would only put header files for functions that are meant for consumption by other packages. These have to be header only functions or properly registered with R. Rcpp can do this registration automatically with the Rcpp::interfaces attribute. See for example my dqrng package.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.