Rozwiązanie R_RegisterCCallable
/R_GetCCallable
wskazywanego przez @BrodieG jest prawdopodobnie lepszy niż ten poniżej, przynajmniej wtedy, gdy można zmodyfikować pakiet, w którym wymagana jest rejestracja i gdzie wybór funkcji do wywołania jest prosty (poniższy przykład pochodzi z bardziej lub mniej skomplikowanego kodu R, który wybiera jeden z kilka funkcji, które można przekazać do C, podobnie jak lapply's FUN, gdzie wybór funkcji jest łatwiejszy do wdrożenia w R niż C). Istotne jest również, Linking to other packages, gdy chce się ujawnić/uzyskać dostęp do wielu funkcji.
Podobną możliwością jest, aby zarejestrować swoje funkcje C w opakowaniu rje, używając coś podobnego, w 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);
}
i w przestrzeni nazw
useDynLib(rje, .registration=TRUE)
adres wpisu poziomu C punkt jest wtedy dostępny w R jako
rje_c = getNativeSymbolInfo(".rje", PACKAGE="rje")
i może być używany w drugim pakiecie za pomocą tego jako argument do funkcji C, np
.Call(.use_rje, rje_c$address, "A User")
z
#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);
}
to zbyt niezdarny, aby zilustrować to w pakiecie, ale zasada jest zilustrowany brzmienie złożyć 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);
}
skompilować z R CMD SHLIB rje.c
i używać jako
> dyn.load("rje.so")
> .Call(".use_rje", getNativeSymbolInfo("rje")$address, "A User")
Hello 'A User'
NULL
Zobacz ** [Łączenie z procedurami macierzystymi w sekcji Inne pakiety] (http://cran.r-project.org/doc/manuals/r-release/R-exts.html#Linking-to-native- rutyny-w-innych pakietach) ** z "Pisanie rozszerzeń R"; klucz wydaje się używać wywołania 'R_RegisterCCalla' w' R_init_rje' w pliku C (ostatnia funkcja w pierwszym bloku przykładu @MartinMorgan). Zastrzeżenie: Nie próbowałem tego. – BrodieG