I am looking for a good approach to build a C++ GUI application. Its core is generating whole bunch of tcl code and execute it through Tcl C++ API (#include <tcl.h>). The GUI provides an easy way for users to complete those tcl scripting tasks.
In other words, inside each callback function associated with the GUI control, it's like using ostringstream to populate tcl code and passes it to tcl interpreter. Eg:
bool execTclProc1(options) {
ostringstream oss;
oss << "package require MyPackage \n";
string optionsForTcl = genOptionsForTcl(options);
oss << "myTclProc1 " << optionsForTcl << endl;
if(Tcl_Eval(interp, oss.c_str() == TCL_OK) {
// print out some messages to the GUI message window
}
...
}
The down side of this design:
Hard to debug tcl code error. Since every change in tcl code needs to re-compile the C code. Although a fast way is to write and test tcl code in tcl interactive shell. But a lot of tcl code is populated in C++, not hard-coded. So it's not so feasible.
Whole bunch of tcl code is written in C++ routines. This makes it hard to maintain.
I want to seek some insights from the community.
Can't you use the Tk toolkit called as library functions from C++?
Also, there is Tk/C++ - don't know how good it is. They overloaded operator- and use expression templates so that the C++ code like like Tcl. Pretty cool!
Related
I am making a small system and I want to be able to toggle "verbose" text output in the whole system.
I have made a file called globals.h:
namespace REBr{
extern bool console_verbose = false;
}
If this is true I want all my classes to print a message to the console when they are constructing, destructing, copying or doing pretty much anything.
For example:
window(string title="",int width=1280,int height=720):
Width(width),Height(height),title(title)
{
if(console_verbose){
std::cout<<"Generating window #"<<this->instanceCounter;
std::cout<<"-";
}
this->window=SDL_CreateWindow(title.c_str(),0,0,width,height,SDL_WINDOW_OPENGL);
if(console_verbose)
std::cout<<"-";
if(this->window)
{
this->glcontext = SDL_GL_CreateContext(window);
if(console_verbose)
std::cout<<".";
if(this->glcontext==NULL)
{
std::cout<<"FATAL ERROR IN REBr::WINDOW::CONSTR_OPENGLCONTEXT: "<<SDL_GetError()<<std::endl;
}
}
else std::cout<<"FATAL ERROR IN REBr::WINDOW::CONSTR_WINDOW: "<<SDL_GetError()<<std::endl;
if(console_verbose)
std::cout<<">done!"<<endl;
}
Now as you can see I have a lot of ifs in that constructor. And I REALLY dont want that since that will slow down my application. I need this to be as fast as possible without removing the "loading bar" (this helps me determine at which function the program stopped functioning).
What is the best/fastest way to accomplish this?
Everying in my system is under the namespace REBr
Some variants to achieve that:
Use some logger library. It is the best option as it gives you maximum flexibility and some useful experience ;) And you haven't to devise something. For example, look at Google GLOG.
Define some macro, allowing you to turn on/off all these logs by changing only the macro. But it isn't so easy to write such marco correctly.
Mark your conditional flag as constexpr. That way you may switch the flag and, depending on its value, compiler will optimise ifs in compiled program. But ifs will still be in code, so it looks kinda bulky.
Anyway, all these options require program recompilation. W/o recompilation it is impossible to achieve the maximum speed.
I often use a Logger class that supports debug levels. A call might look like:
logger->Log(debugLevel, "%s %s %d %d", timestamp, msg, value1, value2);
The Logger class supports multiple debug levels so that I can fine tune the debug output. This can be set at any time through the command line or with a debugger. The Log statement uses a variable length argument list much like printf.
Google's logging module is widely used in the industry and supports logging levels that you can set from the command line. For example (taken from their documentation)
VLOG(1) << "I'm printed when you run the program with --v=1 or higher";
VLOG(2) << "I'm printed when you run the program with --v=2 or higher";
You can find the code here https://github.com/google/glog and the documentation in the doc/ folder.
I'm interested in implementing a program written in C++ inside a Ruby on Rails 4 App.
The C++ app runs in console and works by giving it a file, it processes it and then it outputs another file.
I found 'Ruby Inline', a gem that allegedly allows the use of foreign code:
https://rubygems.org/gems/RubyInline
gem 'RubyInline', '~> 3.12', '>= 3.12.4'
Inline allows you to write foreign code within your ruby code. It automatically determines if the code in question has changed and builds it only when necessary. The extensions are then automatically loaded into the class/module that defines it. You can even write extra builders that will allow you to write inlined code in any language. Use Inline::C as a template and look at Module#inline for the required API.
According to the documentation, it allows the use of C and C++ programs like this:
require 'inline'
class MyTest
inline(:C) do |builder|
builder.include '<iostream>'
builder.add_compile_flags '-x c++', '-lstdc++'
builder.c '
void hello(int i) {
while (i-- > 0) {
std::cout << "hello" << std::endl;
}
}'
end
end
t = MyTest.new()
t.hello(3)
The problem is that I'm not entirely sure how to implement it with a larger C++ program made out of multiple files, I'm not proficient in C++.
This seems like a gem to add the C++ code inside a ruby script and the C++ program is made out of multiple files and folders.
Will Ruby Inline work for what I want to do or is there a better option out there?
Is there a way to call the C++ app directly without putting it inside a ruby file?
The file to be given to the C++ app will be uploaded via the web interface, how can I feed it to the C++ program so it outputs the result?
Ruby supports the functionality to run native commands using the ` character. For example, we have a C++ program below, that takes two arguments, and then prints to standard output both of them, concatenated together. The course code for this program can be seen below:
#include <iostream>
int main(int argc, char ** argv){
std::cout << argv[1] << argv[2] << std::endl;
return 0;
}
While the C++ code, really only needs to be compiled a single time, and this step wouldn't likely be necessary, we can compile it from within ruby by doing the following: (You can replace g++ with the compiler of your choice.) We will set the variable success to true if the command successfully compiles, false otherwise.
pathToSource = "your/path/to/file.cpp"
outputBinaryFile = "your/desired/output/file.bin"
success = system("g++ #{pathToSource} -o #{outputBinaryFile}")
Now that we have compiled our code, we can execute it by running the following in ruby:
word1 = "Hello"
word2 = "World"
commandOutput = `./#{outputBinaryFile} '#{word1}' '#{word2}'`
Which will set commandOutput to: "HelloWorld\n"
You may need to change small things such as the compiler depending on the system that you are running, but this should function for you on *NIX systems.
I have a large program written in C++ that uses std::cout in a lot of places. I am building an NCurses version and std::cout destroys that interface.
Is there a way to reroute the console output from std::cout to something like cdk_swindow?
A simple way to do this would be to override the << operator. This way in your case you can use cdk_swindow
I rememeber std:cout didn't work in ncurses framwork and i use printf function, you use a regex with sed and convert you std:cout to printf function.But it's hard code and dirty anyway.
I'd look at the CDK examples (http://invisible-island.net/cdk/)
Since CDK 'takes over' an Xterm, you probably will want to create a wrapper function that spews the text that used to go to the console, into something like CDKVIEWER.
I am doing image analysis using C++ in the QtCreator environment. In order to build a learning model, I want to use the TreeBagger class from MATLAB, which is really powerful. Can I call MATLAB from QtCreator, give it some parameters, and get back the classification error? Can I do this without using mex files?
From QProcess's Synchronous Process API example:
QProcess gzip;
gzip.start("gzip", QStringList() << "-c");
if (!gzip.waitForStarted())
return false;
gzip.write("Qt rocks!");
gzip.closeWriteChannel();
if (!gzip.waitForFinished())
return false;
QByteArray result = gzip.readAll();
The concept to from this example is the process of being able to execute matlab w/ whatever settings that would be preferable and begin writing a script to it immediately. After the write; you can close the channel, wait for response, then read the results from matlab. Uunfortunately, I'm not experienced w/ it to provide a more direct example, but this is the concept for the most case. Please research the documentation for anything else.
Matlab has an "engine" interface described here to let standalone programs call matlab functions. It has the advantage that you can call engPutVariableand engGetVariable to transfer your data in binary format (I think it works by using shared memory between your process and matlab, but I'm not sure on this), so you don't have to convert your data to ascii and parse the result from ascii.
For c++ you might want to write a wrapper class for RAII or have a look at http://www.codeproject.com/Articles/4216/MATLAB-Engine-API, where this has already been done.
I need to launch some script using QProcess.
For this, under windows, I use QProcess::execute("cmd [...]");.
However, this won't work if I go under some other OS such as Linux.
So, I was wondering if the best solution to make that code portable, would be to interfere with a mutliplatform scripting solution, such as TCL for exemple.
So I use : QProcess:execute("tclsh text.tcl"); and it works.
But, I got three questions concerning that problem. Because I'm not sure of what I've done.
Will execute() execute tclsh with the file test.tcl both under Windows and Linux wherever I execute it ? It seems to do so, but I want to be sure ! Is there any bad scenario that can happen ?
Is this a good solution ? I know lots of people have way more experience than I do, and I'd be grateful for anything I could learn !
Why not using std::system() ? Is it less portable ?
While this isn't a total answer, I can point out a few things.
In particular, tclsh is quite happy under Windows; it's a major supported platform. The main problem that could happen in practice is if you pass a filename with a space in it (this is distinctly more likely under Windows than on a Unix due to differences in community practice). However, the execute() as you have written it has no problems. Well, as long as tclsh is located on the PATH.
The other main option for integrating Tcl script execution with Qt is to link your program against the Tcl binary library and use that. Tcl's API is aimed at C, so it should be pretty simple to use from C++ (if a little clunky from a C++ perspective):
// This holds the description of the API
#include "tcl.h"
// Initialize the Tcl library; *call only once*
Tcl_FindExecutable(NULL);
// Make an evaluation context
Tcl_Interp *interp = Tcl_CreateInterp();
// Execute a script loaded from a file (or whatever)
int resultCode = Tcl_Eval(interp, "source test.tcl");
// Check if an error happened and print the error if it did
if (resultCode == TCL_ERROR) {
std::cerr << "ERROR: " << Tcl_GetString(Tcl_GetObjResult(interp)) << std::endl;
}
// Squelch the evaluation context
Tcl_DeleteInterp(interp);
I'm not a particularly great C++ coder, but this should give the idea. I have no idea about QProcess::execute() vs std::system().
A weak point of your solution is that on windows you'll have to install tclsh. There is no tclsh on Solaris either. May be somewhere else.
Compared to std::system(), QProcess gives you more control and information about the process of executing your command. If all you need is just to execute script (without receiving the output, for example) - std::system() is a good choice.
What I've used in a similar situation:
#ifdef Q_OS_WIN
mCommand = QString("cmd /C %1 %2").arg(command).arg(args);
#else
mCommand = QString("bash %1 %2").arg(command).arg(args);
#endif