Dear list,
I am trying to embed R into a C++ program. After some tinkering,
reading the documentation and browsing the source code I have this
more or less working. A very very condensed and very simplified
version of the code is included below.
The program can create plots. However, after the plot is initially
drawn it is no longer updated. When scaling or updating the plot the
window becomes blank, and the window also doesn't want to close. I
suspect that my R_ReadConsole routine is the problem. This routine
waits for user input and returns this (which I thought it should). It
seems that this causes the event loop that updates the windows to also
be on hold. I did have a look at 'Rstd_ReadConsole' in
'src/unix/sys-std.c', but I can't figure out what exactly happens in
this routine.
How do I ensure that the windows keep being updated?
Presently I am working under Linux. However, I also want to be able to
run my code under windows, so I hope there is a cross-platform
solution. Thanks in advance.
Regards,
Jan van der Laan
===== The example code =====
#include <iostream>
#include <iomanip>
#include <string>
static void R_WriteConsoleEx (const char *buf, int buflen, int otype) {
std::string output(buf, buflen);
std::cout << output;
}
static void R_WriteConsole (const char *buf, int buflen) {
R_WriteConsoleEx(buf, buflen, 0);
}
static int R_ReadConsole (const char *prompt, unsigned char *buf, int
buflen, int hist) {
std::cout << prompt;
std::string input;
std::cin >> input;
for (unsigned int i = 0; i < input.length(); ++i) {
buf[i] = input[i];
buf[i+1] = '\n';
buf[i+2] = '\0';
if ((int)i >= buflen-3) break;
}
return input.length();
}
extern "C" {
#define R_INTERFACE_PTRS
#include <Rinterface.h>
int Rf_initialize_R(int ac, char **av); /* in ../unix/system.c */
extern int R_running_as_main_program; /* in ../unix/system.c */
}
int main(int ac, char **av)
{
R_running_as_main_program = 1;
Rf_initialize_R(ac, av);
ptr_R_WriteConsoleEx = &R_WriteConsoleEx;
ptr_R_WriteConsole = &R_WriteConsole;
ptr_R_ReadConsole = &R_ReadConsole;
R_Outputfile = NULL;
R_Consolefile = NULL;
Rf_mainloop(); /* does not return */
return 0;
}
Plot window does not update in embedded code
7 messages · Jan van der Laan, Thomas Friedrichsmeier, Simon Urbanek
Hi,
On Wednesday 21 July 2010, Jan van der Laan wrote:
How do I ensure that the windows keep being updated?
in RKWard we run the following periodically during idle phases:
// this basically copied from R's unix/sys-std.c (Rstd_ReadConsole)
#ifndef Q_WS_WIN
for (;;) {
fd_set *what;
what = R_checkActivityEx(R_wait_usec > 0 ? R_wait_usec : 50, 1,
Rf_onintr);
R_runHandlers(R_InputHandlers, what);
if (what == NULL) break;
}
/* This seems to be needed to make Rcmdr react to events. Has this always
been the case? It was commented out for a long time, without anybody noticing.
*/
R_PolledEvents ();
#else
R_ProcessEvents();
#endif
Regards
Thomas
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 198 bytes
Desc: This is a digitally signed message part.
URL: <https://stat.ethz.ch/pipermail/r-devel/attachments/20100721/c1088344/attachment.bin>
Use R_CheckUserInterrupt() The code below is very fragile and unix-specific. Cheers, Simon
On Jul 21, 2010, at 3:45 PM, Thomas Friedrichsmeier wrote:
Hi, On Wednesday 21 July 2010, Jan van der Laan wrote:
How do I ensure that the windows keep being updated?
in RKWard we run the following periodically during idle phases:
// this basically copied from R's unix/sys-std.c (Rstd_ReadConsole)
#ifndef Q_WS_WIN
for (;;) {
fd_set *what;
what = R_checkActivityEx(R_wait_usec > 0 ? R_wait_usec : 50, 1,
Rf_onintr);
R_runHandlers(R_InputHandlers, what);
if (what == NULL) break;
}
/* This seems to be needed to make Rcmdr react to events. Has this always
been the case? It was commented out for a long time, without anybody noticing.
*/
R_PolledEvents ();
#else
R_ProcessEvents();
#endif
Regards
Thomas
______________________________________________ R-devel at r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-devel
On Jul 21, 2010, at 4:28 PM, Simon Urbanek wrote:
Use R_CheckUserInterrupt()
Actually, the above is true but assumes that you're running R's REPL and not your own R_ReadConsole (it will work even in your ReadConsole but unix handlers are not run in that case so only some events will work).
The code below is very fragile and unix-specific.
That is true, too, but even after R_ProcessEvenrts refactorization the handlers are still-unix specific so I stand corrected and you still have to run handlers manually (note that you don't need PolledEvents anymore since they are part of the handlers). Cheers, Simon
On Wednesday 21 July 2010, Jan van der Laan wrote:
How do I ensure that the windows keep being updated?
in RKWard we run the following periodically during idle phases:
// this basically copied from R's unix/sys-std.c (Rstd_ReadConsole)
#ifndef Q_WS_WIN
for (;;) {
fd_set *what;
what = R_checkActivityEx(R_wait_usec > 0 ? R_wait_usec : 50, 1,
Rf_onintr);
R_runHandlers(R_InputHandlers, what);
if (what == NULL) break;
}
/* This seems to be needed to make Rcmdr react to events. Has this always
been the case? It was commented out for a long time, without anybody noticing.
*/
R_PolledEvents ();
#else
R_ProcessEvents();
#endif
Regards
Thomas
______________________________________________ R-devel at r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-devel
______________________________________________ R-devel at r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-devel
Thomas, Simon, Thank you for your answers. I will have a look at the code Thomas gave me and probably also have another look at src/unix/sys-std.c. I'll get back when I have this working, or, more likely, when I can't get this to work. As for the example code. I know it is very fragile. I tried to make a minimal complete example that showed the problem without having to attach hundreds of lines of code that nobody will read. However, what parts are unix specific? Is it the int Rf_initialize_R and R_running_as_main_program? What non os specific options do I have? Again thank you for your answers. Regards, Jan On Wed, Jul 21, 2010 at 10:52 PM, Simon Urbanek
<simon.urbanek at r-project.org> wrote:
On Jul 21, 2010, at 4:28 PM, Simon Urbanek wrote:
Use R_CheckUserInterrupt()
Actually, the above is true but assumes that you're running R's REPL and not your own R_ReadConsole (it will work even in your ReadConsole but unix handlers are not run in that case so only some events will work).
The code below is very fragile and unix-specific.
That is true, too, but even after R_ProcessEvenrts refactorization the handlers are still-unix specific so I stand corrected and you still have to run handlers manually (note that you don't need PolledEvents anymore since they are part of the handlers). Cheers, Simon
On Wednesday 21 July 2010, Jan van der Laan wrote:
How do I ensure that the windows keep being updated?
in RKWard we run the following periodically during idle phases:
// this basically copied from R's unix/sys-std.c (Rstd_ReadConsole)
#ifndef Q_WS_WIN
? ? ?for (;;) {
? ? ? ? ? ? ?fd_set *what;
? ? ? ? ? ? ?what = R_checkActivityEx(R_wait_usec > 0 ? R_wait_usec : 50, 1,
Rf_onintr);
? ? ? ? ? ? ?R_runHandlers(R_InputHandlers, what);
? ? ? ? ? ? ?if (what == NULL) break;
? ? ?}
? ? ?/* This seems to be needed to make Rcmdr react to events. Has this always
been the case? It was commented out for a long time, without anybody noticing.
*/
? ? ?R_PolledEvents ();
#else
? ? ?R_ProcessEvents();
#endif
Regards
Thomas
______________________________________________ R-devel at r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-devel
______________________________________________ R-devel at r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-devel
______________________________________________ R-devel at r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-devel
On Jul 22, 2010, at 3:31 AM, Jan van der Laan wrote:
Thomas, Simon, Thank you for your answers. I will have a look at the code Thomas gave me and probably also have another look at src/unix/sys-std.c. I'll get back when I have this working, or, more likely, when I can't get this to work. As for the example code. I know it is very fragile. I tried to make a minimal complete example that showed the problem without having to attach hundreds of lines of code that nobody will read. However, what parts are unix specific? Is it the int Rf_initialize_R and R_running_as_main_program? What non os specific options do I have?
I was talking about the snippet Thomas sent - not your code - yours was nicely minimalistic. The issue with running the handlers by hand is that it's unix-only. But as I corrected in my second e-mail - it is the way to go right now since there is no alternative at the moment (again, you may get away with simply calling R_CheckUserInterrupt() but some devices may be using input handlers in which case it is not sufficient). The fact that you can check handlers manually is a good thing but it may be worth considering providing an API call like R_idle(int timeoutMillis) that does the job across all platforms. Cheers, Simon
Again thank you for your answers. Regards, Jan On Wed, Jul 21, 2010 at 10:52 PM, Simon Urbanek <simon.urbanek at r-project.org> wrote:
On Jul 21, 2010, at 4:28 PM, Simon Urbanek wrote:
Use R_CheckUserInterrupt()
Actually, the above is true but assumes that you're running R's REPL and not your own R_ReadConsole (it will work even in your ReadConsole but unix handlers are not run in that case so only some events will work).
The code below is very fragile and unix-specific.
That is true, too, but even after R_ProcessEvenrts refactorization the handlers are still-unix specific so I stand corrected and you still have to run handlers manually (note that you don't need PolledEvents anymore since they are part of the handlers). Cheers, Simon
On Wednesday 21 July 2010, Jan van der Laan wrote:
How do I ensure that the windows keep being updated?
in RKWard we run the following periodically during idle phases:
// this basically copied from R's unix/sys-std.c (Rstd_ReadConsole)
#ifndef Q_WS_WIN
for (;;) {
fd_set *what;
what = R_checkActivityEx(R_wait_usec > 0 ? R_wait_usec : 50, 1,
Rf_onintr);
R_runHandlers(R_InputHandlers, what);
if (what == NULL) break;
}
/* This seems to be needed to make Rcmdr react to events. Has this always
been the case? It was commented out for a long time, without anybody noticing.
*/
R_PolledEvents ();
#else
R_ProcessEvents();
#endif
Regards
Thomas
______________________________________________ R-devel at r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-devel
______________________________________________ R-devel at r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-devel
______________________________________________ R-devel at r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-devel
5 days later
Took a while to find enough time to have a good look at this, but I have this working now. I am using the for-loop calling the handlers. Using only R_CheckUserInterrupt() did not work. It was a bit of work to track down all of the function declarations in R's source. Thanks! Regards, Jan On Thu, Jul 22, 2010 at 4:06 PM, Simon Urbanek
<simon.urbanek at r-project.org> wrote:
On Jul 22, 2010, at 3:31 AM, Jan van der Laan wrote:
Thomas, Simon, Thank you for your answers. I will have a look at the code Thomas gave me and probably also have another look at src/unix/sys-std.c. I'll get back when I have this working, or, more likely, when I can't get this to work. As for the example code. I know it is very fragile. I tried to make a minimal complete example that showed the problem without having to attach hundreds of lines of code that nobody will read. However, what parts are unix specific? Is it the int Rf_initialize_R and R_running_as_main_program? What non os specific options do I have?
I was talking about the snippet Thomas sent - not your code - yours was nicely minimalistic. The issue with running the handlers by hand is that it's unix-only. But as I corrected in my second e-mail - it is the way to go right now since there is no alternative at the moment (again, you may get away with simply calling R_CheckUserInterrupt() but some devices may be using input handlers in which case it is not sufficient). The fact that you can check handlers manually is a good thing but it may be worth considering providing an API call like R_idle(int timeoutMillis) that does the job across all platforms. Cheers, Simon
Again thank you for your answers. Regards, Jan On Wed, Jul 21, 2010 at 10:52 PM, Simon Urbanek <simon.urbanek at r-project.org> wrote:
On Jul 21, 2010, at 4:28 PM, Simon Urbanek wrote:
Use R_CheckUserInterrupt()
Actually, the above is true but assumes that you're running R's REPL and not your own R_ReadConsole (it will work even in your ReadConsole but unix handlers are not run in that case so only some events will work).
The code below is very fragile and unix-specific.
That is true, too, but even after R_ProcessEvenrts refactorization the handlers are still-unix specific so I stand corrected and you still have to run handlers manually (note that you don't need PolledEvents anymore since they are part of the handlers). Cheers, Simon
On Wednesday 21 July 2010, Jan van der Laan wrote:
How do I ensure that the windows keep being updated?
in RKWard we run the following periodically during idle phases:
// this basically copied from R's unix/sys-std.c (Rstd_ReadConsole)
#ifndef Q_WS_WIN
? ? ?for (;;) {
? ? ? ? ? ? ?fd_set *what;
? ? ? ? ? ? ?what = R_checkActivityEx(R_wait_usec > 0 ? R_wait_usec : 50, 1,
Rf_onintr);
? ? ? ? ? ? ?R_runHandlers(R_InputHandlers, what);
? ? ? ? ? ? ?if (what == NULL) break;
? ? ?}
? ? ?/* This seems to be needed to make Rcmdr react to events. Has this always
been the case? It was commented out for a long time, without anybody noticing.
*/
? ? ?R_PolledEvents ();
#else
? ? ?R_ProcessEvents();
#endif
Regards
Thomas
______________________________________________ R-devel at r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-devel
______________________________________________ R-devel at r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-devel
______________________________________________ R-devel at r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-devel