View source: R/externalCalls.R
nimbleExternalCall | R Documentation |
Given C header information, a function that takes scalars or pointers can be called from a compiled nimbleFunction. If non-scalar return values are needed, an argument can be selected to behave as the return value in nimble.
nimbleExternalCall(
prototype,
returnType,
Cfun,
headerFile,
oFile,
where = getNimbleFunctionEnvironment()
)
prototype |
Argument type information. This can be provided as an R function using |
returnType |
Return object type information. This can be provided similarly to |
Cfun |
Name of the external function (character). |
headerFile |
Name (possibly including file path) of the header file where Cfun is declared. |
oFile |
Name (possibly including path) of the .o file where Cfun has been compiled. Spaces in the path may cause problems. |
where |
An optional |
The only argument types allowed in Cfun are double
, int
, and bool
, corresponding to nimbleFunction
types double
, integer
, and logical
, respectively.
If the dimensionality is greater than zero, the arguments in Cfun
should be pointers. This means it will typically be necessary to pass additional integer arguments telling Cfun
the size(s) of non-scalar arguments.
The return argument can only be a scalar or void. Since non-scalar arguments are passed by pointer, you can use an argument to return results from Cfun
. If you wish to have a nimbleFunction
that uses one argument of Cfun
as a return object, you can wrap the result of nimbleExternalCall
in another nimbleFunction
that allocates the return object. This is useful for using Cfun
in a nimbleModel
. See example below.
Note that a nimbleExternalCall
can only be executed in a compiled nimbleFunction
, not an uncompiled one.
If you have problems with spaces in file paths (e.g. for oFile
), try compiling everything locally by including dirName = "."
as an argument to compileNimble
.
Note that if you use Rcpp
to generate object files, NIMBLE's use of the --preclean
option to R CMD SHLIB
can cause failures, so you may need to run nimbleOptions(precleanCompilation=FALSE)
to prevent removal of needed object files.
A nimbleFunction
that takes the indicated input arguments, calls Cfun
, and returns the result.
Perry de Valpine
nimbleRcall
for calling arbitrary R code from compiled nimbleFunction
s.
## Not run:
sink('add1.h')
cat('
extern "C" {
void my_internal_function(double *p, double*ans, int n);
}
')
sink()
sink('add1.cpp')
cat('
#include <cstdio>
#include "add1.h"
void my_internal_function(double *p, double *ans, int n) {
printf("In my_internal_function\\n");
/* cat reduces the double slash to single slash */
for(int i = 0; i < n; i++)
ans[i] = p[i] + 1.0;
}
')
sink()
system('g++ add1.cpp -c -o add1.o')
Radd1 <- nimbleExternalCall(function(x = double(1), ans = double(1),
n = integer()){}, Cfun = 'my_internal_function',
headerFile = file.path(getwd(), 'add1.h'), returnType = void(),
oFile = file.path(getwd(), 'add1.o'))
## If you need to use a function with non-scalar return object in model code,
## you can wrap it in another nimbleFunction like this:
model_add1 <- nimbleFunction(
run = function(x = double(1)) {
ans <- numeric(length(x))
Radd1(x, ans, length(x))
return(ans)
returnType(double(1))
})
demoCode <- nimbleCode({
for(i in 1:4) {x[i] ~ dnorm(0,1)} ## just to get a vector
y[1:4] <- model_add1(x[1:4])
})
demoModel <- nimbleModel(demoCode, inits = list(x = rnorm(4)),
check = FALSE, calculate = FALSE)
CdemoModel <- compileNimble(demoModel, showCompilerOutput = TRUE)
## End(Not run)
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.