Skip to content

Commit

Permalink
R DLL/SO not required (!)
Browse files Browse the repository at this point in the history
.. 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
  • Loading branch information
liversedge committed Apr 27, 2016
1 parent 90e61b6 commit 4bfad2e
Show file tree
Hide file tree
Showing 5 changed files with 38 additions and 82 deletions.
File renamed without changes.
6 changes: 0 additions & 6 deletions src/Core/main.cpp
Expand Up @@ -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
Expand Down
89 changes: 38 additions & 51 deletions src/R/RTool.cpp
Expand Up @@ -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();
Expand All @@ -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());

Expand Down Expand Up @@ -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()
{
Expand Down
4 changes: 0 additions & 4 deletions src/R/RTool.h
Expand Up @@ -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
Expand Down
21 changes: 0 additions & 21 deletions src/src.pro
Expand Up @@ -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

}
}

Expand Down

0 comments on commit 4bfad2e

Please sign in to comment.