[rkward/frameworks] rkward/rbackend/rkwarddevice: Fix MSVC-compiled backend crash on RK()-device close.
Thomas Friedrichsmeier
thomas.friedrichsmeier at ruhr-uni-bochum.de
Sun Feb 28 17:15:38 UTC 2016
Git commit 8fcbd52dfca73b9ee6e8f3266c7b2eb94336825b by Thomas Friedrichsmeier.
Committed on 28/02/2016 at 17:15.
Pushed by tfry into branch 'frameworks'.
Fix MSVC-compiled backend crash on RK()-device close.
M +13 -1 rkward/rbackend/rkwarddevice/rkgraphicsdevice_setup.cpp
M +11 -0 rkward/rbackend/rkwarddevice/rkgraphicsdevice_stubs.cpp
http://commits.kde.org/rkward/8fcbd52dfca73b9ee6e8f3266c7b2eb94336825b
diff --git a/rkward/rbackend/rkwarddevice/rkgraphicsdevice_setup.cpp b/rkward/rbackend/rkwarddevice/rkgraphicsdevice_setup.cpp
index 90a3a40..5afd04d 100644
--- a/rkward/rbackend/rkwarddevice/rkgraphicsdevice_setup.cpp
+++ b/rkward/rbackend/rkwarddevice/rkgraphicsdevice_setup.cpp
@@ -55,6 +55,10 @@ struct RKGraphicsDeviceDesc {
QString default_family;
QString default_symbol_family;
pDevDesc rdevdesc;
+#ifdef _MSC_VER
+ // See RKD_Close()
+ pGEDevDesc rgdevdesc;
+#endif
};
#include "rkgraphicsdevice_stubs.cpp"
@@ -76,7 +80,11 @@ void RKStartGraphicsDevice (double width, double height, double pointsize, const
pDevDesc dev;
BEGIN_SUSPEND_INTERRUPTS {
/* Allocate and initialize the device driver data */
- dev = (pDevDesc) calloc (1, sizeof(DevDesc));
+#ifdef _MSC_VER
+ dev = (pDevDesc) malloc (sizeof (DevDesc));
+#else
+ dev = (pDevDesc) calloc (1, sizeof (DevDesc)); // don't really understand this, but R needs it this way (while MSVC hates it)
+#endif
// NOTE: The call to RKGraphicsDeviceBackendTransmitter::instance(), here is important beyond error checking. It might *create* the instance and connection, if this is the first use.
if (!(dev && RKGraphicsDeviceBackendTransmitter::instance () && desc->init (dev, pointsize, family, bg))) {
free (dev);
@@ -89,6 +97,10 @@ void RKStartGraphicsDevice (double width, double height, double pointsize, const
pGEDevDesc gdd = GEcreateDevDesc (dev);
gdd->displayList = R_NilValue;
GEaddDevice2 (gdd, "RKGraphicsDevice");
+#ifdef _MSC_VER
+ // See RKD_Close()
+ desc->rgdevdesc = gdd;
+#endif
}
} END_SUSPEND_INTERRUPTS;
diff --git a/rkward/rbackend/rkwarddevice/rkgraphicsdevice_stubs.cpp b/rkward/rbackend/rkwarddevice/rkgraphicsdevice_stubs.cpp
index c6c619a..217fbcd 100644
--- a/rkward/rbackend/rkwarddevice/rkgraphicsdevice_stubs.cpp
+++ b/rkward/rbackend/rkwarddevice/rkgraphicsdevice_stubs.cpp
@@ -360,6 +360,17 @@ static void RKD_MetricInfo (int c, R_GE_gcontext *gc, double* ascent, double* de
static void RKD_Close (pDevDesc dev) {
RKGraphicsDataStreamWriteGuard guard;
WRITE_HEADER (RKDClose, dev);
+#ifdef _MSC_VER
+ // Ok, this is a terribly crude HACK, obivously, and it's just waiting to come back to bite us. However:
+ // We had to allocate the DevDesc in our own (MSVC-compiled) code (that's the way it is done), but if we allow R to delete
+ // it (also, as usual; in its MinGW-compiled code), we get a crash. Whatever the _exact_ reason. So what we do here is
+ // reset R's pointer, and do the free, ourselves. Fortunately, we can do this, and fortunately, the pointer is no longer
+ // needed at this point. At least not in R 3.2.3...
+ // If (or when) this breaks, we could try to just call some other device's init-routine, then hijack that device. Or out-source
+ // the RKGraphicsDevice backend init code into an R package...
+ static_cast<RKGraphicsDeviceDesc*> (dev->deviceSpecific)->rgdevdesc->dev = NULL;
+ free (dev);
+#endif
delete static_cast<RKGraphicsDeviceDesc*> (dev->deviceSpecific);
}
More information about the rkward-tracker
mailing list