Markku Mielityinen
2005-Apr-02 12:28 UTC
[Rd] Building new graphic device drivers with g++
Dear Group, I'm trying to build a set of new graphic device drivers. I use the devNull example a a beginning point: $ R CMD SHLIB devNull.c gcc -shared -L/usr/local/lib -o devNull.so devNull.o (everything works OK) $ R CMD SHLIB devNull.cpp g++ -shared -L/usr/local/lib -o devNull.so devNull.o (everything works OK) The difficulties start when trying to compile manually. I compile the library with no errors: g++ devNull.cpp -o devNull.so -I/usr/lib/R/include -I/usr/local/include -L/usr/local/lib -lm -lpthread -lsupc++ -lg2c -shared -fPIC -O2 -Wall -Wunused -Wconversion -fno-exceptions -g -pipe -m32 -march=i386 -mtune=pentium4 But when I try to load the library I get: R : Copyright 2004, The R Foundation for Statistical Computing Version 2.0.1 (2004-11-15), ISBN 3-900051-07-0 R is free software and comes with ABSOLUTELY NO WARRANTY. You are welcome to redistribute it under certain conditions. Type 'license()' or 'licence()' for distribution details. R is a collaborative project with many contributors. Type 'contributors()' for more information and 'citation()' on how to cite R or R packages in publications. Type 'demo()' for some demos, 'help()' for on-line help, or 'help.start()' for a HTML browser interface to help. Type 'q()' to quit R.> dyn.load("devNull.so")Error in dyn.load(x, as.logical(local), as.logical(now)) : unable to load shared library "/home/mmmm/R/devNull/src/devNull.so": /home/mmmm/R/devNull/src/devNull.so: undefined symbol: _Z17GEinitDisplayListP10_GEDevDesc>I probably need to link to some "libR.a" module. But where is it? In windows R uses -lR switch but I cannot find that library file in my Fedora Core 3 distribution. Is there a file that defines the compiler switches for R CMD SHLIB compiling? Here is an example code: =devNull.cpp================================================================================ #include <R.h> #include <Rinternals.h> #include <Rgraphics.h> #include <Rdevices.h> #include <R_ext/GraphicsDevice.h> #include <R_ext/GraphicsEngine.h> extern "C" { static Rboolean nullDeviceDriver(NewDevDesc *dev); SEXP do_devNULL() { NewDevDesc *dev = NULL; GEDevDesc *dd; R_CheckDeviceAvailable(); if (!(dev = (NewDevDesc *) calloc(1, sizeof(NewDevDesc)))) return R_NilValue; dev->displayList = R_NilValue; if (!nullDeviceDriver(dev)) { free(dev); error("unable to start NULL device"); } gsetVar(install(".Device"), mkString("NULL"), R_NilValue); dd = GEcreateDevDesc(dev); Rf_addDevice((DevDesc*) dd); GEinitDisplayList(dd); return R_NilValue; } static void NULL_Circle(double x, double y, double r, R_GE_gcontext *gc, NewDevDesc *dev) { Rprintf("circle(%lf,%lf,%lf)\n", x, y, r); } static void NULL_Line(double x1, double y1, double x2, double y2, R_GE_gcontext *gc, NewDevDesc *dev) { Rprintf("line(%lf,%lf,%lf,%lf)\n", x1, y1, x2, y2); } static void NULL_Polygon(int n, double *x, double *y, R_GE_gcontext *gc, NewDevDesc *dev) { Rprintf("polygon(%d)\n", n); } static void NULL_Polyline(int n, double *x, double *y, R_GE_gcontext *gc, NewDevDesc *dev) { Rprintf("polyline(%d)\n", n); } static void NULL_Rect(double x0, double y0, double x1, double y1, R_GE_gcontext *gc, NewDevDesc *dev) { Rprintf("rectangle(%lf,%lf,%lf,%lf)\n", x0, y0, x1, y1); } static void NULL_Text(double x, double y, char *str, double rot, double hadj, R_GE_gcontext *gc, NewDevDesc *dev) { Rprintf("text(%lf,%lf,\"%s\",%lf,%lf)\n", x, y, str, rot, hadj); } static void NULL_NewPage(R_GE_gcontext *gc, NewDevDesc *dev) { Rprintf("newpage\n"); } static void NULL_Close(NewDevDesc *dev) { Rprintf("close\n"); } Rboolean NULL_Open(NewDevDesc *dev) { Rprintf("open\n"); return TRUE; } static void NULL_Activate(NewDevDesc *dev) { Rprintf("activate\n"); } static void NULL_Clip(double x0, double x1, double y0, double y1, NewDevDesc *dev) { Rprintf("clip(%lf,%lf,%lf,%lf)\n", x0, y0, x1, y1); } static void NULL_Deactivate(NewDevDesc *dev) { Rprintf("deactivate\n"); } static void NULL_Mode(int mode, NewDevDesc *dev) { } static Rboolean NULL_Locator(double *x, double *y, NewDevDesc *dev) { return FALSE; } static void NULL_MetricInfo(int c, R_GE_gcontext *gc, double* ascent, double* descent, double* width, NewDevDesc *dev) { *ascent = 0.0; *descent = 0.0; *width = 0.0; } static void NULL_Size(double *left, double *right, double *bottom, double *top, NewDevDesc *dev) { *left = dev->left; *right = dev->right; *bottom = dev->bottom; *top = dev->top; } static double NULL_StrWidth(char *str, R_GE_gcontext *gc, NewDevDesc *dev) { return 0.0; } static void NULL_dot(NewDevDesc *dev) { } static void NULL_Hold(NewDevDesc *dev) { } static Rboolean nullDeviceDriver(NewDevDesc *dev) { dev->deviceSpecific = NULL; /* * Device functions */ dev->open = (Rboolean (*)())NULL_Open; dev->close = (void (*)())NULL_Close; dev->activate = (void (*)())NULL_Activate; dev->deactivate = (void (*)())NULL_Deactivate; dev->size = (void (*)())NULL_Size; dev->newPage = (void (*)())NULL_NewPage; dev->clip = (void (*)())NULL_Clip; dev->strWidth = (double (*)())NULL_StrWidth; dev->text = (void (*)())NULL_Text; dev->rect = (void (*)())NULL_Rect; dev->circle = (void (*)())NULL_Circle; dev->line = (void (*)())NULL_Line; dev->polyline = (void (*)())NULL_Polyline; dev->polygon = (void (*)())NULL_Polygon; dev->locator = (Rboolean (*)())NULL_Locator; dev->mode = (void (*)())NULL_Mode; dev->hold = (void (*)())NULL_Hold; dev->metricInfo = (void (*)())NULL_MetricInfo; /* * Initial graphical settings */ dev->startfont = 1; dev->startps = 10; dev->startcol = R_RGB(0, 0, 0); dev->startfill = R_TRANWHITE; dev->startlty = LTY_SOLID; dev->startgamma = 1; /* * Start device */ if(!NULL_Open(dev)) { return FALSE; } /* * Device physical characteristics */ dev->left = 0; dev->right = 1000; dev->bottom = 0; dev->top = 1000; dev->cra[0] = 10; dev->cra[1] = 10; dev->xCharOffset = 0.4900; dev->yCharOffset = 0.3333; dev->yLineBias = 0.1; dev->ipr[0] = 1.0/72; dev->ipr[1] = 1.0/72; /* * Device capabilities */ dev->canResizePlot= FALSE; dev->canChangeFont= FALSE; dev->canRotateText= TRUE; dev->canResizeText= TRUE; dev->canClip = TRUE; dev->canHAdj = 2; dev->canChangeGamma = FALSE; dev->displayListOn = TRUE; dev->newDevStruct = 1; return TRUE; } } ============================================================================================ Best regards, Markku Mielityinen
On Sat, 2 Apr 2005, Markku Mielityinen wrote:> Dear Group, > > I'm trying to build a set of new graphic device drivers. I use the > devNull example a a beginning point: > > $ R CMD SHLIB devNull.c > gcc -shared -L/usr/local/lib -o devNull.so devNull.o > (everything works OK) > > $ R CMD SHLIB devNull.cpp > g++ -shared -L/usr/local/lib -o devNull.so devNull.o > (everything works OK)Is this the same devNull.cpp as below? If so, I don't believe that it did work.> The difficulties start when trying to compile manually. I compile the > library with no errors: > > g++ devNull.cpp -o devNull.so -I/usr/lib/R/include -I/usr/local/include > -L/usr/local/lib -lm -lpthread -lsupc++ -lg2c -shared -fPIC -O2 -Wall > -Wunused -Wconversion -fno-exceptions -g -pipe -m32 -march=i386 > -mtune=pentium4Where did that come from? Why do you need the Fortran runtime linked into C++ code? What has pthreads to do with this?> But when I try to load the library I get: > > R : Copyright 2004, The R Foundation for Statistical Computing > Version 2.0.1 (2004-11-15), ISBN 3-900051-07-0 > > R is free software and comes with ABSOLUTELY NO WARRANTY. > You are welcome to redistribute it under certain conditions. > Type 'license()' or 'licence()' for distribution details. > > R is a collaborative project with many contributors. > Type 'contributors()' for more information and > 'citation()' on how to cite R or R packages in publications. > > Type 'demo()' for some demos, 'help()' for on-line help, or > 'help.start()' for a HTML browser interface to help. > Type 'q()' to quit R. > >> dyn.load("devNull.so") > Error in dyn.load(x, as.logical(local), as.logical(now)) : > unable to load shared library > "/home/mmmm/R/devNull/src/devNull.so": > /home/mmmm/R/devNull/src/devNull.so: undefined symbol: > _Z17GEinitDisplayListP10_GEDevDesc >> > > I probably need to link to some "libR.a" module.Please don't hypothesize out of thin air. Nothing there says anything about libR.a. However, it does refer to a symbol you did not call, so you should have noticed that something in the name was amiss.> But where is it? In windows R uses -lR switch but I cannot find that > library file in my Fedora Core 3 distribution.You only need -lR if you built a shared-R-lib version of R, a configure option. If it were needed, R SHLIB would have made use of it. Notice the name mangling: It seems you are trying to build a C++ graphics device driver. Where did you get the idea that was supported? You seem unaware how to include C headers in C++ code, but it would be easier to write C as C and not as pseudo-C++.> Is there a file that defines the compiler switches for R CMD SHLIB > compiling?Is there some local tuition about the differences between C and C++ you could obtain?> Here is an example code: > > =devNull.cpp===========================================================> =====================> > #include <R.h> > #include <Rinternals.h> > #include <Rgraphics.h> > #include <Rdevices.h> > #include <R_ext/GraphicsDevice.h> > #include <R_ext/GraphicsEngine.h> > > extern "C" { > > static Rboolean nullDeviceDriver(NewDevDesc *dev); > > SEXP do_devNULL() { > NewDevDesc *dev = NULL; > GEDevDesc *dd; > > R_CheckDeviceAvailable(); > if (!(dev = (NewDevDesc *) calloc(1, sizeof(NewDevDesc)))) > return R_NilValue; > dev->displayList = R_NilValue; > if (!nullDeviceDriver(dev)) { > free(dev); > error("unable to start NULL device"); > } > gsetVar(install(".Device"), mkString("NULL"), R_NilValue); > dd = GEcreateDevDesc(dev); > Rf_addDevice((DevDesc*) dd); > GEinitDisplayList(dd); > return R_NilValue; > } > static void NULL_Circle(double x, double y, double r, > R_GE_gcontext *gc, > NewDevDesc *dev) { > Rprintf("circle(%lf,%lf,%lf)\n", x, y, r); > } > static void NULL_Line(double x1, double y1, double x2, double y2, > R_GE_gcontext *gc, > NewDevDesc *dev) { > Rprintf("line(%lf,%lf,%lf,%lf)\n", x1, y1, x2, y2); > } > static void NULL_Polygon(int n, double *x, double *y, > R_GE_gcontext *gc, > NewDevDesc *dev) { > Rprintf("polygon(%d)\n", n); > } > static void NULL_Polyline(int n, double *x, double *y, > R_GE_gcontext *gc, > NewDevDesc *dev) { > Rprintf("polyline(%d)\n", n); > } > static void NULL_Rect(double x0, double y0, double x1, double y1, > R_GE_gcontext *gc, > NewDevDesc *dev) { > Rprintf("rectangle(%lf,%lf,%lf,%lf)\n", x0, y0, x1, y1); > } > static void NULL_Text(double x, double y, char *str, > double rot, double hadj, > R_GE_gcontext *gc, > NewDevDesc *dev) { > Rprintf("text(%lf,%lf,\"%s\",%lf,%lf)\n", x, y, str, rot, hadj); > } > static void NULL_NewPage(R_GE_gcontext *gc, > NewDevDesc *dev) { > Rprintf("newpage\n"); > } > static void NULL_Close(NewDevDesc *dev) { > Rprintf("close\n"); > } > Rboolean NULL_Open(NewDevDesc *dev) { > Rprintf("open\n"); > return TRUE; > } > static void NULL_Activate(NewDevDesc *dev) { > Rprintf("activate\n"); > } > static void NULL_Clip(double x0, double x1, double y0, double y1, > NewDevDesc *dev) { > Rprintf("clip(%lf,%lf,%lf,%lf)\n", x0, y0, x1, y1); > } > static void NULL_Deactivate(NewDevDesc *dev) { > Rprintf("deactivate\n"); > } > static void NULL_Mode(int mode, NewDevDesc *dev) { > } > static Rboolean NULL_Locator(double *x, double *y, NewDevDesc *dev) { > return FALSE; > } > static void NULL_MetricInfo(int c, > R_GE_gcontext *gc, > double* ascent, double* descent, > double* width, NewDevDesc *dev) { > *ascent = 0.0; > *descent = 0.0; > *width = 0.0; > } > static void NULL_Size(double *left, double *right, > double *bottom, double *top, > NewDevDesc *dev) { > *left = dev->left; > *right = dev->right; > *bottom = dev->bottom; > *top = dev->top; > } > static double NULL_StrWidth(char *str, > R_GE_gcontext *gc, > NewDevDesc *dev) { > return 0.0; > } > static void NULL_dot(NewDevDesc *dev) { > } > static void NULL_Hold(NewDevDesc *dev) { > } > static Rboolean nullDeviceDriver(NewDevDesc *dev) { > dev->deviceSpecific = NULL; > /* > * Device functions > */ > dev->open = (Rboolean (*)())NULL_Open; > dev->close = (void (*)())NULL_Close; > dev->activate = (void (*)())NULL_Activate; > dev->deactivate = (void (*)())NULL_Deactivate; > dev->size = (void (*)())NULL_Size; > dev->newPage = (void (*)())NULL_NewPage; > dev->clip = (void (*)())NULL_Clip; > dev->strWidth = (double (*)())NULL_StrWidth; > dev->text = (void (*)())NULL_Text; > dev->rect = (void (*)())NULL_Rect; > dev->circle = (void (*)())NULL_Circle; > dev->line = (void (*)())NULL_Line; > dev->polyline = (void (*)())NULL_Polyline; > dev->polygon = (void (*)())NULL_Polygon; > dev->locator = (Rboolean (*)())NULL_Locator; > dev->mode = (void (*)())NULL_Mode; > dev->hold = (void (*)())NULL_Hold; > dev->metricInfo = (void (*)())NULL_MetricInfo; > /* > * Initial graphical settings > */ > dev->startfont = 1; > dev->startps = 10; > dev->startcol = R_RGB(0, 0, 0); > dev->startfill = R_TRANWHITE; > dev->startlty = LTY_SOLID; > dev->startgamma = 1; > /* > * Start device > */ > if(!NULL_Open(dev)) { > return FALSE; > } > /* > * Device physical characteristics > */ > dev->left = 0; > dev->right = 1000; > dev->bottom = 0; > dev->top = 1000; > dev->cra[0] = 10; > dev->cra[1] = 10; > dev->xCharOffset = 0.4900; > dev->yCharOffset = 0.3333; > dev->yLineBias = 0.1; > dev->ipr[0] = 1.0/72; > dev->ipr[1] = 1.0/72; > /* > * Device capabilities > */ > dev->canResizePlot= FALSE; > dev->canChangeFont= FALSE; > dev->canRotateText= TRUE; > dev->canResizeText= TRUE; > dev->canClip = TRUE; > dev->canHAdj = 2; > dev->canChangeGamma = FALSE; > dev->displayListOn = TRUE; > > dev->newDevStruct = 1; > return TRUE; > } > > } > > =======================================================================> =====================> > Best regards, > Markku Mielityinen > > ______________________________________________ > R-devel@stat.math.ethz.ch mailing list > https://stat.ethz.ch/mailman/listinfo/r-devel > >-- Brian D. Ripley, ripley@stats.ox.ac.uk Professor of Applied Statistics, http://www.stats.ox.ac.uk/~ripley/ University of Oxford, Tel: +44 1865 272861 (self) 1 South Parks Road, +44 1865 272866 (PA) Oxford OX1 3TG, UK Fax: +44 1865 272595