R DLL/SO not required (!)

.. we can register routines when embedding via the
   R_getEmbeddingDLLInfo()

.. so we just register our functions directly now
   in RTool rather than needing a dynamic library.

.. its cleaner and there are no nasty casts and build
   settings required
This commit is contained in:
Mark Liversedge
2016-04-27 08:11:01 +01:00
parent e73858b2fa
commit 9608830908
5 changed files with 38 additions and 82 deletions

View File

@@ -270,12 +270,6 @@ main(int argc, char *argv[])
// create the singleton in the main thread
// will be shared by all athletes and all charts (!!)
rtool = new RTool(argc,argv);
// and run the .First function
rtool->R->parseEvalQNT(".First()");
// now map functions once the DLL is loaded
rtool->registerRoutines();
#endif
// create the application -- only ever ONE regardless of restarts

View File

@@ -49,6 +49,32 @@ RTool::RTool(int argc, char**argv)
R->set_callbacks(callbacks);
dev = new RGraphicsDevice();
// register our functions
// initialise the parameter table
R_CMethodDef cMethods[] = {
{ "GC.display", (DL_FUNC) &RGraphicsDevice::GCdisplay, 0 ,0, 0 },
{ "GC.athlete", (DL_FUNC) &RTool::athlete, 0 ,0, 0 },
{ "GC.athlete.home", (DL_FUNC) &RTool::athleteHome, 0 ,0, 0 },
{ "GC.activities", (DL_FUNC) &RTool::activities, 0 ,0, 0 },
{ "GC.activity", (DL_FUNC) &RTool::activity, 0 ,0, 0 },
{ "GC.metrics", (DL_FUNC) &RTool::metrics, 0 ,0, 0 },
{ NULL, NULL, 0, 0, 0 }
};
R_CallMethodDef callMethods[] = {
{ "GC.display", (DL_FUNC) &RGraphicsDevice::GCdisplay, 0 },
{ "GC.athlete", (DL_FUNC) &RTool::athlete, 0 },
{ "GC.athlete.home", (DL_FUNC) &RTool::athleteHome, 0 },
{ "GC.activities", (DL_FUNC) &RTool::activities, 0 },
{ "GC.activity", (DL_FUNC) &RTool::activity, 0 },
{ "GC.metrics", (DL_FUNC) &RTool::metrics, 0 },
{ NULL, NULL, 0 }
};
// set them up
DllInfo *info = R_getEmbeddingDllInfo();
R_registerRoutines(info, cMethods, callMethods, NULL, NULL);
// lets get the version early for the about dialog
R->parseEvalNT("print(R.version.string)");
QStringList &strings = callbacks->getConsoleOutput();
@@ -61,21 +87,18 @@ RTool::RTool(int argc, char**argv)
// load the dynamix library and create function wrapper
// we should put this into a source file (.R)
R->parseEvalNT(QString(".First <- function() {\n"
" dyn.load(\"RGoldenCheetah.so\")\n"
"}\n"
"GC.display <- function() { .Call(\"GC.display\") }\n"
"GC.athlete <- function() { .Call(\"GC.athlete\") }\n"
"GC.athlete.home <- function() { .Call(\"GC.athlete.home\") }\n"
"GC.activities <- function() { .Call(\"GC.activities\") }\n"
"GC.activity <- function() { .Call(\"GC.activity\") }\n"
"GC.metrics <- function() { .Call(\"GC.metrics\") }\n"
"GC.version <- function() {\n"
" return(\"%1\")\n"
"}\n"
"GC.build <- function() {\n"
" return(%2)\n"
"}\n")
R->parseEvalNT(QString("GC.display <- function() { .Call(\"GC.display\") }\n"
"GC.athlete <- function() { .Call(\"GC.athlete\") }\n"
"GC.athlete.home <- function() { .Call(\"GC.athlete.home\") }\n"
"GC.activities <- function() { .Call(\"GC.activities\") }\n"
"GC.activity <- function() { .Call(\"GC.activity\") }\n"
"GC.metrics <- function() { .Call(\"GC.metrics\") }\n"
"GC.version <- function() {\n"
" return(\"%1\")\n"
"}\n"
"GC.build <- function() {\n"
" return(%2)\n"
"}\n")
.arg(VERSION_STRING)
.arg(VERSION_LATEST).toStdString());
@@ -113,42 +136,6 @@ RTool::RTool(int argc, char**argv)
starting = false;
}
extern "C" {
int assigndl(SEXP (**p)(SEXP(*[])()), DL_FUNC x)
{
*p = (SEXP(*)(SEXP(*[])()))(*x);
return 0;
}
};
void
RTool::registerRoutines()
{
// the dynamic libray is loaded so we should be able to find
// the initialisation function now
// get the value
DL_FUNC dd = R_GetCCallable("RGoldenCheetah", "GCinitialiseFunctions");
// change signature
SEXP (*p)(SEXP(*[])());
// cast
assigndl(&p, dd);
// array of all the function pointers (just 1 for now)
SEXP (*fn[6])() = { &RGraphicsDevice::GCdisplay,
&RTool::athlete,
&RTool::athleteHome,
&RTool::activities,
&RTool::activity,
&RTool::metrics };
// dereference and call, if not found all is lost ....
if (p) *p(fn);
}
void
RTool::configChanged()
{

View File

@@ -48,10 +48,6 @@ class RTool {
static SEXP metrics();
bool starting;
// to link GC.xxx() functions to the routine
// stubs in the RGoldenCheetah DLL/SO/DYLIB
void registerRoutines();
};
// there is a global instance created in main

View File

@@ -278,27 +278,6 @@ contains(DEFINES, "GC_WANT_R") {
HEADERS += Charts/RChart.h Charts/RCanvas.h
SOURCES += Charts/RChart.cpp Charts/RCanvas.cpp
# how to build an R shlib from source, listed in SOURCE_RSHLIBS below
# we only have one for now, but could possibly add more. This is to
# use the public R API and avoid using RInside and Rcpp
rshlib.name = rshlib
rshlib.input = SOURCE_RSHLIBS
rshlib.dependency_type = TYPE_C
macx { rshlib.CONFIG += no_link }
unix { rshlib.output = $${OUT_PWD}/${QMAKE_FILE_BASE}.so }
win32 { rshlib.output = $${OUT_PWD}/${QMAKE_FILE_BASE}.dll }
rshlib.commands = $$R_HOME/bin/R CMD SHLIB ${QMAKE_FILE_IN} && $${QMAKE_COPY} ${QMAKE_FILE_PATH}/${QMAKE_FILE_OUT} $${OUT_PWD}
QMAKE_EXTRA_COMPILERS += rshlib
## post link on OSX we need to copy the so file
macx {
QMAKE_POST_LINK += $${QMAKE_COPY} $${OUT_PWD}/RGoldenCheetah.so $${OUT_PWD}/GoldenCheetah.app/Contents/MacOS
}
## R bootstrap dynamic libraries, used to register C methods
## to avoid RInside/Rccp
SOURCE_RSHLIBS = R/RGoldenCheetah.c
}
}