Embedding a Ruby interpreter in a C++ app - c++

I'm hoping to use Ruby as a scripting language for my game engine. I've found the usual articles describing how to call Ruby classes from C++ code and vice versa (e.g. here) but I can't quite see how to do what I want with that way of working...
My engine currently uses a little language I wrote myself with Flex and Bison, and a little stack based virtual machine. Scripts don't always run right through from start to finish, for instance they sometimes includes commands like "sleep for 2 seconds" or "wait until character has finished walking", so the scheduler keeps tabs on the status of each script and an instruction pointer, and knows when to resume them, and so on.
So it seems that I really need some kind of embedded Ruby interpreter that I can exercise a certain degree of control over, rather than simply calling Ruby methods. Or am I just being obtuse and missing something?
I'm working in Microsoft Visual C++, so ideally any solution would compile nice and easily in that.

Here's an example including error handling.
#include <iostream>
#include <ruby.h>
using namespace std;
int main(void)
{
ruby_init();
ruby_init_loadpath();
int status;
rb_load_protect(rb_str_new2("./test.rb"), 0, &status);
if (status) {
VALUE rbError = rb_funcall(rb_gv_get("$!"), rb_intern("message"), 0);
cerr << StringValuePtr(rbError) << endl;
};
ruby_finalize();
return status;
}

You're on the right track. The key is to do something similar to the section on Embedding Concepts in the link you posted. In simple terms it's little more than:
ruby_init();
ruby_script("some_script");
You may need to copy over all the #ifdef stuff from main.c to get everything working. From then it's a matter of building an API to your C++ functions you want to expose, and depending on your design, multi-threading the thing.

You could always re-design the way the scripts work to suit the script engine rather than trying to get the engine to work with the original scripting paradigms.
So, if you had this:
proc:
action 1
action 2
sleep a bit
action 3
end
which would require the script to be suspended on the sleep line, do this:
proc
action1
action2
set timer (time, callback_proc)
end
callback_proc
action3
end
which lets the scripting engine finish each method neatly. It wouldn't need many changes to the hosting side - each version requires some form of event system which can restart the script engine.

There is a guide about how to embed ruby into a C++ application. That may be helpful. Otherwise go to the Ruby documentation.
The Embed Ruby in C article may be helpful, too.

I think what your going to want to do is use Ruby's threads. I've done a fair bit of digging through the Ruby threading code and I know that (where pthreads is available) sleep is implemented in a non-blocking fashion using pthread_cond_timedwait. This unblocks the interpreter so that other threads can continue execution.
Your own code is going to have to respect Ruby's threads when it comes to interacting with the Ruby interpreter. They've still got a Global VM Lock in Ruby which means you should be careful about modifying anything in the interpreter without having the lock yourself.

Related

Is there a way to send C/C++ commands using Johnny-Five?

Currently running a number of ESP8266s flashed with StandardFirmataWiFi using a central linux machine running J5. So instead setting up a bunch of micro-controllers to run autonomously, they are all WiFi enabled and under the command of a single machine.
So far this has been working very well. I'm very familiar with JS, not super familiar with C/C+
But occasionally I find example code in C/C+ for which I can't find a J5 equivalent.
Question:
Is it possible to issue C/C+ (or even Python) commands from Johnny-Five? So in other words instead of the central machine issuing J5-only commands to the micro-controllers, is there way to have J5 send C/C+ snippets? If so, that would make it easier to work directly with demo/community-shared code while also making it easier for JS-fluent developers to transition toward C.
C and C++ are compiled languages. That means you need a compiler in order to translate C or C++ code into something that can be run on a processor. Because of that there's no eval() in C or C++, no function which can text a chunk of text and process it as C or C++ code.
So there cannot be a way for Johnny-Five or anything else to send C or C++ code to an ESP8266 - the ESP8266 is not capable of running a C or C++ compiler and cannot translate C code into something it can execute. You could potentially transfer compiled ESP8266 code but there are so many difficulties with that approach that you shouldn't waste time considering it.
Like Javascript, Python is an interpreted language. It has an eval() function that you can execute a string as Python code. If you can arrange to have a handler on the ESP8266 receive a string and then eval it, you could send Python commands from a remote program.
Beware that there are huge gaping security issues with doing something like that - you're literally allowing a remote program to execute whatever it feels like on the ESP8266.

NCurses not restoring terminal behavior

Hello dear Communauts,
I'm am creating a terminal animated status report for a parallel software I'm developing. I'm using NCurses.
I'm having an issue related to the restoring of the standard behavior of the terminal.
After running my software the terminal keeps having just 24 lines, no matter if I call endwin() or I don't.
Here the simplified code:
int size=10;
initscr();
refresh();
while(KeepAlive){
int j=1;
mvprintw(j,0,/*Blah blah header*/));
for(int i=0;i<size;i++){
j++;
mvprintw(j,0,/*Some blah blah*/);
}
refresh();
usleep(1000000);
}
endwin();
KeepAlive is a control variable changed by another thread (so the while is not infinite loop, but controlled loop).
After running this software my terminal has only 24 lines, echo works, but there's plenty of blank space.
Thanks a lot for your help, have fun
EDIT:
I would like to share with you some information I found while attempting to solve my issue:
curses (ncurses) is perfectly working under openMP, then you can imagine some threads doing your math calculations and one thread (only one, be aware) giving out some runtime infos.
curse (ncurses) is NOT compatible with MPI. Well, the right stating would be is "not completely" compatible with MPI. MPI is really sophisticated about stdin/stdout/stderr, since all outputs from all MPI-processes could be redirected to a display (which could be specified). Using any advanced terminal output overriding library will take to a fault of the code, or unexpected behaviors.
That's supported by the MPI faq:
Maybe. But probably not.
Open MPI provides fairly sophisticated stdin / stdout / stderr forwarding. >However, it does not work well with curses, ncurses, readline, or other >sophisticated I/O packages that generally require direct control of the terminal.
Every application and I/O library is different -- you should try to see if yours >is supported. But chances are that it won't work.
Sorry. :-(
found here (MPI reference).
What I've discovered is that even if you appoint only one MPI-process to manage all the curses output (just that process calls initscr() at the beginning and endwin() at the end of his part of code) there is no way to force curses to use the full terminal (only default UNIX 24x80 will be available).
Once MPI has been finalized your whole terminal will keep working in 24x80 mode until reset is called.
Thanks to all communauts that helped me,
Have fun
gf
One possible solution is to completely decouple your text GUI from the rest of the MPI code and make both parts talk to each other via the client/server mechanism of MPI-2. That means:
Run the GUI as singleton MPI program, i.e. one that calls MPI_Init{_thread} but is not started via mpiexec. It then should open a listening port by calling MPI_Open_port. The call returns a string port name that has to be supplied to the compute part of the application. The GUI part should then start listening for connections by calling the blocking MPI_Comm_accept.
The compute part is started as usual via mpiexec. It should connect to the GUI by calling MPI_Comm_connect given the port name from (1).
The combination of MPI_Comm_accept in the GUI and MPI_Comm_connect in the compute part establishes an intercommunicator that can be used for sending messages between the two parts. The compute part could e.g. send periodic status messages to the GUI. If necessary, the intercommunicator could be further "flattened" to an intracommunicator.
Once the computation is finished, the communication part should disconnect by calling MPI_Comm_disconnect.
The GUI should call MPI_Close_port and finish its own execution.
In that scenario, the GUI part could be a text mode curses application started locally or remotely via SSH, an X11 GUI application, or whatever else there.
It should work. The comment about "parallel" suggests multithreading, which can mean that your output is not flushed as one might expect.
Likely this is the same issue (Ncurses limited output size) for which more information was given. Neither question provides enough detail to offer more than generic advice.

Integrate a python scripting console for a C++ library

I have a library with classes and public methods written in C++.
I would like, from inside an interactive program written in C++ and Qt, to send commands to a parser in Python language which in turn converts them to call to methods and functions of my library.
Something similar to what is done in Octave/Matlab, a string is processed by a parser which then executes internally the commands.
Somewhere in my C++ library I have a function
int myFooCPPfunction(int value)
{
return value*value;
}
then during the execution of my program, I want to start a console and type in Python syntax:
for i in range(0,20):
print("%d" % myFooCPPfunction(i))
The command I gave then updates the internal state of my program for example.
I think it is a matter of writing Python code that links to C++. It seems to me that things like boost::python already do it...I ask your suggestion on which is the better way to write the bindings.
Second point: how to integrate that thing in an interactive shell launched from a Qt application?
Some online projects like QConsole should do something similar, but QConsole appears to be a very outdated project.
Thank you!
PythonQt was created for exactly this purpose.

Clear console using C++ with Xcode?

I'm trying to make a C++ console application using Xcode 4.1, but I can't find the command for cleaning the screen while the program is executing...
Any ideas? Thanks!
OSX doesn't have "consoles" the way Windows does. It has pseudoterminals, which act like an old-fashioned glass terminal to the program running "inside" them, and like a bidirectional pipe to the program that set them up. That outer program can do whatever it likes with the inner program's input and output. Notable examples of such programs are Terminal.app, which emulates the venerable VT-100, and ssh, which forwards the I/O over a secure channel to its own controlling terminal (which is probably itself a pseudoterminal). This is all by way of saying that there isn't a method that's guaranteed to work, because maybe the program on the outside of the pseudoterminal doesn't have a "screen" that you can meaningfully "clear." (Expect is a good example of a program like that.)
Having said that, though, if there is a screen, these days you can pretty much count on it to respect the VT-100 control codes. So this should do what you want:
std::cout << "\033[2J" << std::flush;
If you find that you need even one more control code, though, it's time to hook your program up to ncurses, which presents a nice friendly API to all the tricks that modern terminal windows are capable of, and will also have your back in the increasingly unlikely event that your program is attached to a terminal (or a program emulating a terminal) that is not a VT-100 nor one of its descendants.

How do I create a timer run my program repeatedly? C++

I want create timer in my program so that I can cause it to rerun every minute and I don't know how to do it in a C++ Application. In C# I could just create a timer but I'm struggling here now...
sleep(); is not an option because as far as I know it makes your program inactive for X seconds, I need my app to be active and working, calculating all the time. This is because my code is used to constantly input information into a MS Access table. I was able to create the necessary components of my code to connect and perform the insert/update to the table but this is just on of the many components to the code that I am creating. Please help me with this little (or big?) problem, I'm very new to C++ and learning ATM, but I am developing a fast learning curve. Thanks
I suppose you work on Windows, since you mentioned C#. So take a look at SetTimer, and if it is a MFC app, then look at CWnd::SetTimer.
Every platform provides api for creating a timer, which will give you a callback usually after timer expires. You can just search for the api available on your platform.
If you are using windows use setTimer function.
If you're using C++ .NET, you can use the same Timer class(es) as C#, just use the C++ syntax (using gcnew instead of new, use the ^ for GC references).
Otherwise you could just have a loop:
while (should_keep_looping) {
// do what you need to do
// if necessary:
sleep(1);
}
See here: http://www.cplusplus.com/forum/beginner/317/
There is on built in "timer" in C++, and you are correct about the behavior of sleep(). The above thread describes a custom implementation.
if you have a window you can use its message queue, as suggested by Als and Marius in their answers
you can use some task dispatcher and some timer to register a callback, e.g. functionality provided by Boost.Asio and its deadline_timer (example)
you can check if timer expired between your tasks manually as proposed in BlackJack's link
or you can create separate thread and make it call your callback when time came. Pros: you can use sleep() there and you callback will be called in parallel with your main thread. Cons: worry about synchronization