C++ function not available
Asked Answered
C

2

9

I have the following file cumsum_bounded.cpp

#include <Rcpp.h>
using namespace Rcpp;

//' Cumulative sum.
//' @param x numeric vector
//' @param low lower bound
//' @param high upper bound
//' @param res bounded numeric vector
//' @export
//' @return bounded numeric vector
// [[Rcpp::export]]
NumericVector cumsum_bounded(NumericVector x, double low, double high) {
    NumericVector res(x.size());
    double acc = 0;
    for (int i=0; i < x.size(); ++i) {
        acc += x[i];
        if (acc < low)  acc = low;
        else if (acc > high)  acc = high;
        res[i] = acc;
    }
    return res;
}

I then Build & Reload and test out my new function.

cumsum_bounded(c(1, -2, 3), low = 2, high = 10)
[1] 1 0 3

Then I build the documentation. devtools::document()

When I Build & Reload everything compiles fine.

But when I run cumsum_bounded(c(1, 2, 3), low= 2, high = 10) I get the error:

Error in .Call("joshr_cumsum_bounded", PACKAGE = "joshr", x, low, high) : 
  "joshr_cumsum_bounded" not available for .Call() for package "joshr"

NAMESPACE

# Generated by roxygen2: do not edit by hand

export(cumsum_bounded)

Update:

If I create a new project as above and DON'T use the Build & Reload function but rather devtools::loadall(), it will work. But once I press that Build & Reload button, it goes sideways.

Chickadee answered 13/4, 2016 at 17:51 Comment(9)
Which files were updated when you ran document()?Roxieroxine
You may want to add a tag devtools -- as Rcpp itself works as documented. And we don't say anything (good or bad) about devtools. I would just run Rcpp::compileAttributes() the the very fine manual says.Reprehend
@DirkEddelbuettel The Build & Reload button executes Rcpp::compileAttributes().Chickadee
@Roxieroxine cumsum_bounded.RdChickadee
So if you're an RStudio person, just leave devtools out and do File -> New Project to select 'Create a Package' and select Rcpp. It. Will. Just. Work. Then add your code.Reprehend
That is how I created the project.Chickadee
Out of pure curiosity, what is the error when doing: joshr::cumsum_bounded(c(1, 2, 3), low= 2, high = 10) ?Kareykari
Also, what is the contents of your NAMESPACE file?Kareykari
@Coatless The error is the same.Chickadee
J
15

You likely need the line

useDynLib(<pkg>) ## substitute your package name for <pkg>

in your NAMESPACE file. If you're using roxygen2, you can add a line e.g. #' @useDynLib <pkg> somewhere in your documentation, substituting your package name for <pkg> as appropriate.

EDIT: And in response to your other error message, you likely need to import something from Rcpp, e.g. add the line @importFrom Rcpp evalCpp.

January answered 13/4, 2016 at 21:8 Comment(6)
Error in cumsum_bounded(c(1, 2, 3), low = 1, high = 3) : function 'enterRNGScope' not provided by package 'Rcpp'Chickadee
Thank you for the solution.Chickadee
These are both elementary errors you would have avoided either by a) reading the documentation (I know, I know, ...) or b) have a template package created.Reprehend
I think there is a c) @DirkEddelbuettel -- forgetting that when you let roxygen2 generate the NAMESPACE file that you need the directive somewhere. You'd probably do this if you were starting from scratch, but when you're moving things from legacy code this sort of detail can slip through the cracks.Maintain
@DirkEddelbuettel I commonly create a pure-R package and then later sprinkle C++ fragments in where performance is needed. Using a template package isn't applicable to that situation. Docs still are, of course.Miner
@KenWilliams I do that too at times but more often than not copy my functions into the template package. In any event, you are entirely free to ignore the available helpers and make your life as difficult as you choose to. ;-)Reprehend
F
0

Adding this answer since I Googled here from a different context. It's not strictly related to OP's original question, but I'm hoping it's helpful for others who wind up here from similar origins.

I was getting the error:

function 'enterRNGScope' not provided by package 'Rcpp'

I solved this by adding loadNamespace("Rcpp") to my package's .onLoad() hook.

The more typical alternative is to add import(Rcpp) or importFrom(Rcpp, evalCpp) to your package's NAMESPACE (which can of course be accomplished with roxygen2 as #' @importFrom Rcpp evalCpp).

Falchion answered 8/12, 2022 at 21:53 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.