La soluzione R_RegisterCCallable
/R_GetCCallable
puntato da @BrodieG è probabilmente migliore di quello qui sotto, almeno quando si può modificare il pacchetto in cui è richiesta la registrazione e dove la scelta della funzione da chiamare è diretta (l'esempio qui sotto è il codice R più o meno complicato che sceglie uno dei diverse funzioni passano a C, proprio come l'argomento FUN di lapply, dove la scelta della funzione è molto più facile da implementare in R che C). Rilevante è anche Linking to other packages quando si desidera esporre/accedere a molte funzioni.
Una possibilità correlato è per registrare i tuoi funzioni C nel pacchetto RJE, utilizzando qualcosa di simile, in R_init_rje.c
#include <Rinternals.h>
#include <R_ext/Rdynload.h>
SEXP rje(SEXP who) {
Rprintf("Hello %s\n", CHAR(STRING_ELT(who, 0)));
return R_NilValue;
}
static const R_CallMethodDef callMethods[] = {
{".rje", (DL_FUNC) &rje, 1},
{NULL, NULL, 0}
};
void R_init_rje(DllInfo * info)
{
R_registerRoutines(info, NULL, callMethods, NULL, NULL);
}
e nello spazio dei nomi
useDynLib(rje, .registration=TRUE)
L'indirizzo della voce C-level punto è quindi disponibile in R come
rje_c = getNativeSymbolInfo(".rje", PACKAGE="rje")
e può essere utilizzato in altro pacchetto utilizzando come argomento a una funzione C, ad esempio,
.Call(.use_rje, rje_c$address, "A User")
con
#include <Rinternals.h>
#include <R_ext/Rdynload.h>
/* convenience definition of the function template */
typedef SEXP RJE_C_FUN(SEXP who);
SEXP use_rje(SEXP rje_c_fun, SEXP who) {
/* retrieve the function pointer, using an appropriate cast */
RJE_C_FUN *fun = (RJE_C_FUN *) R_ExternalPtrAddr(rje_c_fun);
return fun(who);
}
È troppo goffa per illustrare questo in un pacchetto, ma il principio è illustrato dal seguente presentare rje.c
#include <Rinternals.h>
#include <R_ext/Rdynload.h>
/* convenience definition of the function template */
typedef SEXP RJE_C_FUN(SEXP who);
SEXP rje(SEXP who) {
Rprintf("Hello '%s'\n", CHAR(STRING_ELT(who, 0)));
return R_NilValue;
}
SEXP use_rje(SEXP rje_c_fun, SEXP who) {
/* retrieve the function pointer, using an appropriate cast */
RJE_C_FUN *fun = (RJE_C_FUN *) R_ExternalPtrAddr(rje_c_fun);
return fun(who);
}
static const R_CallMethodDef callMethods[] = {
{".rje", (DL_FUNC) &rje, 1},
{".use_rje", (DL_FUNC) &use_rje, 2},
{NULL, NULL, 0}
};
void R_init_rje(DllInfo * info)
{
R_registerRoutines(info, NULL, callMethods, NULL, NULL);
}
Compilare con R CMD SHLIB rje.c
, e l'uso come
> dyn.load("rje.so")
> .Call(".use_rje", getNativeSymbolInfo("rje")$address, "A User")
Hello 'A User'
NULL
Vedere la sezione ** [Collegamento alle routine native in altri pacchetti] (http://cran.r-project.org/doc/manuals/r-release/R-exts.html#Linking-to-native- routine-in-altri-pacchetti) ** di "Scrittura delle estensioni R"; la chiave sembra utilizzare una chiamata a 'R_RegisterCCallable' in' R_init_rje' nel file C (l'ultima funzione nel primo blocco dell'esempio @MartinMorgan). Disclaimer: non ho provato questo. – BrodieG