C++ executing a code from a text file - c++

The title says it all. Like a compiler but not the same. I want a certain part of the code to be executed from an outer source in C++. And I don't know if that is even possible as it is in Javascript, Python etc.
Let's say I got a text file titled sample.txt like this:
int a = 10, c;
cin >> c;
cout << a + c;
And I'll call the text file in main() function and compiled the .exe file. When I run it, is it possible for it behave dynamically as if the code from the file is embedded in there and write 10 + input? The source file should be changed and different results will apply next time it runs. It's just an example piece of code by the way, I might want to run some for/while loops and if conditions etc.
PS: I know how to read from file and assign it as an integer or write it on the screen, that's not what I want. I need functions to be compiled through. Thanks.

There are a couple of approaches to this.
Fork a command-line compiler and the fork to run the result, passing input and output through STDIN/STDOUT
(While i realize you asked for this from a C++ calling program, i'm demonstrating the idea in bash for simplicity.)
File: run_it.sh:
#!/bin/bash
set -e # Bail on the first error
FN_IN=./sample.txt
FN_WRAPPED=./wrapped.cc
FN_EXE=./wrapped
CC=g++
# Wrap the fragment in a full C++ program and compile it.
function build_wrapper () {
cat > $FN_WRAPPED <<'EOF'
#include <iostream>
using namespace std;
int main(int argc, char **argv) {
EOF
cat $FN_IN >> $FN_WRAPPED
cat >> $FN_WRAPPED <<'EOF'
return 0;
}
EOF
$CC -o $FN_EXE $FN_WRAPPED
}
# Run the wrapper, passing input through STDIN and reading the output from STDOUT.
function run () {
local IN=$1
echo $IN | $FN_EXE
}
# Remove the wrapper (both code and compiled).
function clean_up () {
rm -f $FN_WRAPPED $FN_EXE
}
build_wrapper
IN=24
OUT=$(echo "$IN" | $FN_EXE)
echo "Result = $OUT"
echo "Another result = $(run 16)"
clean_up
$ ./run_it.sh
Result = 34
Another result = 26
Use something like LLVM to compile the function in-process and call it
This approach is very powerful, but also somewhat involved.
In a nutshell, you'd want to
Read sample.txt into memory.
Compile it to a function.
Call the function.
Some possibly-helpful links:
http://fdiv.net/2012/08/15/compiling-code-clang-api
http://www.ibm.com/developerworks/library/os-createcompilerllvm1/
http://llvm.org/docs/tutorial/
https://msm.runhello.com/p/1003
https://db.in.tum.de/teaching/ss15/moderndbs/resources/7/fibonacci.cpp

A compiled C++ program contains only the machine instructions necessary to execute the compiled source code, the language standard does not specify any mechanism for the user to produce additional machine instructions at run time.
In order to provide a scripting capability - the ability to generate program flow in response to the parsing of input text - you have to provide a parser and an execution engine.
int main()
{
std::string cmd;
int op1, op2;
while (cin >> cmd >> op1 >> op2) {
if (cmd == "add")
std::cout << op1 + op2 << "\n";
else if (cmd == "sub")
std::cout << op1 - op2 << "\n";
else
std::cerr << "error\n";
}
}
Many interpreted languages are written in C or C++ in the first place, so it is often possible to build them as a library which you can then incorporate into an application so that the program can call invoke them to provide an embedded scripting language. Common examples of such languages are Lua, Python and JavaScript. Your program can then pass code to be executed to the interpreter.
Writing your own lua interpreter could look like this:
#include <iostream>
#include <string>
#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>
bool get_input(std::string& in)
{
bool result;
do {
std::cout << "lua> " << std::flush;
result = std::getline(std::cin, in);
} while (result && in.empty());
return result;
}
int main (void) {
lua_State *L = lua_open(); // open lua
luaL_openlibs(L); // open standard libraries
std::string in;
while (get_input(in)) {
if (in.empty())
continue;
int error = luaL_loadbuffer(L, in.c_str(), in.size(), "line") ||
lua_pcall(L, 0, 0, 0);
if (error) {
std::cerr << lua_tostring(L, -1) << '\n';
lua_pop(L, 1); // remove the error message from the stack
}
}
lua_close(L);
}
Under linux:
$ g++ -Wall -O3 -o mylua mylua.cpp -I/usr/include/lua5.1 -llua
$ ./mylua
lua> print("hello")
hello
lua> error
[string "line"]:1: '=' expected near '<eof>'
lua>

Related

Ubuntu Terminal C++ program being called in other program stuck, even though they separately work fine

Long story short:
I created a program to get the path to a model file, do something with that information and pass on a different set of information, then i tried to create a wrapper for another program that basically catches the command line arguments and funnels some of them to my program to do its thing.
Simplified program flow.
Software --> args[all] --> Wrapper --> args[some] --> Program --> Output
The problem i now have is, calling my program on its own with hard-coded information or command line arguments equal to what the Wrapper would pass on works both flawlessly. The same goes for the Wrapper it works independently.
It also works to have the Wrapper pass on arguments and call the Program if the model information is wrong, which results in a simple string warning. But if the path to the model is correct it gets stuck in an endless loop and i don't know why. Separate runtimes are 8-11s for the Program and maybe 2s for the Wrapper, but i let it run for about 10min and nothing happened after some dummy print code.
Wrapper:
int main(int argc, char* argv[]){
if(argc > 1){
string tmp0 = argv[1];
string tmp1 = "./program " + tmp0;
const char* model = tmp1.c_str();
int status = system(model);
}
else{
cout << "No Model Information.\n";
}
return 0;
}
Parameters would be: Path to a model file and some other stuff, but only the path to the model would be passed on to the program in this case.
Program:
#include "program.hpp"
int main(int argc, char* argv[]){
if(argc > 1){
string tmp = argv[1];
const char* model = tmp.c_str();
cout << program(model);
}
else{
cout << "At least one defined Argument for the Model needs to be given.\n";
}
return 0;
}
Program Function Pseudo Code:
#include <stdio.h>
string program(const char* model){
string tmp
read(model);
if(model has variables) do
tmp = "has variables";
return tmp
}
--- Edit ---
The program function code is in pseudo code because its too complex and specific to list here without a load of libraries and other stuff being listed. If thats necessary i can try to provide it, but as it is i dont have a small or simple example i can give.
--- End edit ---
I don't understand enough about command line arguments to write sophisticated code, so i know this is more or less shitty, but i only need to be able to execute the program from the wrapper somehow and need to be able to read and pass on specific command line arguments. This is just the best i came up with.
Executing the Program code alone, with correct model information: ~10s execution time
Executing the Program code alone, with wrong model information: ~2s execution time
Executing the Wrapper code alone: ~2s execution time
Executing the Wrapper code, calling the Program code with wrong model information: ~2s execution time
Executing the Wrapper code, calling the Program code with correct model information: endless wait
I just dont get why it doesnt progress even though each works separately.
You can use fork() and execvp() in the unistd.h API. Depending on the return of fork() you can have the wrapper wait or end after launching the command.
Save the source file as args.cpp and compile it with the following command:
$ g++ args.cpp -o args && ./args -l -h -a
#include <cstdio>
#include <unistd.h>
#define SPAWNCMD "ls"
int main(int argc, char* argv[])
{
if(argc > 1)
{
printf("Command to spawn: %s ", SPAWNCMD);
for (unsigned i = 1; i < argc; i++)
printf("%s ", argv[i]);
printf("\n");
if (fork())
if (execvp(SPAWNCMD, argv) == -1)
{
printf("Incorrect termination of SPAWNCMD\n");
return 1;
}
}
else
{
printf("No Model Information.\n");
}
printf("Wrapper program end\n");
return 0;
}

Lua C API Custom Print function, not called when a space is passed in the string

Problem Description:
I have created a custom C++ function print() that is supposed to be pushed as a global onto a table to so the user can use the print() function to print to the debug console. This function works to some extent, however, when you try to print a string with a space in it (over one word) the function is not called at all... This has greatly confused me, as I don't know why. If I were to try and call something such as print("Hello!") the console will have "Hello!" printed to it, but if I were to try and print something such as print("Hello world!") the function will not be called at all, I know this because I have used a message box to alert when the function is called.
Additional Information:
So, the closest thing to this I could find was a question asking how to make a custom print function in C++ with the Lua C API then push it onto the global table. I can already do this, and my function works to some extent. My function isn't being pushed onto the Lua C API's global table, instead to a table that is created by me with lua_newtable(L, s);. However, I've tried it both ways and it makes no difference. This print function does not support tables nor function as of now, I'm just focused on finding out and fixing why the function can't print strings over one word. Just in case you were wondering, Lua v5.1.5 and Microsoft Visual Studio 2017 are used for this. Debug mode, x86.
Code (C++):
If anyone could help me fix this, that would be great!
#include <iostream>
#include <string>
#include <Windows.h>
#pragma comment(lib, "Lua.lib")
#include "lua.hpp"
#include "luaconf.h"
static int print(lua_State* LUASTATE)
{
MessageBoxA(NULL, "Custom print called.", "FUNCTION!", NULL);
int nargs = lua_gettop(LUASTATE);
std::string string = "";
for (int i = 1; i <= nargs; i++)
{
if (i > 1) string += " ";
switch (lua_type(LUASTATE, i))
{
case LUA_TSTRING:
string += (std::string)lua_tostring(LUASTATE, i);
case LUA_TNUMBER:
string += (int)lua_tonumber(LUASTATE, i);
case LUA_TBOOLEAN:
string += (bool)lua_toboolean(LUASTATE, i);
}
}
std::cout << string << "\n";
return 0;
}
int pushs(lua_State* LuaState)
{
luaL_openlibs(LuaState);
lua_newtable(LuaState);
lua_pushcfunction(LuaState, print);
lua_setglobal(LuaState, "print");
lua_settop(LuaState, 0);
return 0;
}
int main()
{
lua_State* ls = luaL_newstate();
lua_State* LS = lua_newthread(ls);
pushs(LS);
while (true)
{
std::cout << " ";
std::string inputo;
std::cin >> inputo;
luaL_dostring(LS, inputo.c_str());
lua_settop(LS, 0);
}
lua_close(LS);
return 0;
}
Main problem
std::cin >> inputo does not read a full line from the standard input. It just reads a single word. So when you type the following input line in your shell:
print("Hello world")
Your main loop breaks it into two separate strings:
print("Hello
world")
And these string are evaluated independently by the Lua interpreter. None of these strings are valid Lua statements, so the interpreter doesn't execute them. lua_dostring will return an error code, and let an error message on the Lua stack.
To work line by line on the standard input, you can use std::getline, which works well in a loop:
std::string line;
while (std::getline(std::cin, line)) {
// do something with line.
}
Side notes
What follows is not directly related to your bug, but look suspicious:
std::string += int (or bool) interprets the int as a single char, and append this single character to the string.
Your switch/case seems to be missing break statements.
lua_State* ls is never closed.

Executing bash shell command and extract output --> invalid file error

I want to extract the framesize of a video from a file. For this purpose, I have launched an ffmpeg command via bash shell, and I want to extract the output. This command is working well in the bash shell, and returns the output as wanted.
ffprobe -v error -count_frames -of flat=s=_ -select_streams v:0 -show_entries stream=nb_read_frames /home/peter/DA/videos/IMG-2014-1-10-10-4-37.avi
I want to call it via C++ and read out the result. I use the IDE Qt 4.8.6 with GCC 4.8 compiler.
For my code, I use this template:
executing shell command with popen
and changed it for my demands to
#include <iostream>
#include <string>
#include <stdio.h>
using namespace std;
int main()
{
FILE* pipe = popen("echo $(ffprobe -v error -count_frames -of flat=s=_ -select_streams v:0 -show_entries stream=nb_read_frames /home/peter/DA/videos/IMG-2014-1-10-10-4-37.avi)", "r");
if(!pipe)
{
cout << "error" << endl;
return 1;
}
char* buffer = new char[512];
string result;
fgets(buffer, sizeof(buffer), pipe) ;
while(!feof(pipe))
{
if(fgets(buffer, sizeof(buffer), pipe) != NULL)
{
cout << buffer << endl;
result += buffer;
}
}
pclose(pipe);
cout << result<< endl;
return 0;
}
The Qt console returned me this warning, and it is rending with return 0:
/home/peter/DA/videos/IMG-2014-1-10-10-4-37.avi: Invalid data found when processing input
and "pipe" is empty.
When I compile the main.cpp file above with g++ in the shell it works nice too.
Old post, but as I see, there are two points here:
Error "Invalid data found when processing input"
That's an ffprobe normal file processing error. Usually it happens when there are errors inside media file, it is not related to c++ program.
ffprobe writes warning/error messages into stderr stream, but popen only captures stdout stream, that's why your program couldn't get that error message trough the pipe.
How get the stdout+stderr in my program
popen allows execute any shell command, so we can use it to redirect stderr into stdout, so your program can get that output too, like this:
FILE *pipe = popen("ffprobe ... 2>&1");
The 2> redirect handle#2 output into current &1 handle#1 output (#1=stdout, #2=stderr).
There's absolute no need to execute FILE *pipe = popen("echo $(ffprobe ...)");, because the final result will be the same: Note that $(...) returns a string with stdout command output, and echo prints it. Totally redundant.
A few observations in order to improve your code:
When a string is too big to be displayed in one screen width, it's better split it into multiple lines (maybe grouping text inside each line within some logic), because that will improve the reading of your code by other people (and eventually by yourself in a few months).
You can do this with a C/C++ compiler feature that concatenates strings separated by spaces (newlines, tab, etc.), ex. "hi " "world" is the same as "hi world" to the compiler.
When your program have to write error messages, use the stderr stream. In c++ that's std::cerr instead std::cout.
Always free memory allocated when it's no loger used (each new has to have a delete)
Avoid use using namespace std;, instead use using std::name; for each standard instance/class that you'll use. Ex. using std::string;, that avoids future problems, specially in big programs. An example of a common error is here. In general avoid using using namespace xxxx;.
Reorganizing your code, we have:
#include <iostream>
#include <stdio.h>
using std::string;
using std::cout;
using std::cerr;
using std::endl;
int main() {
static char ffprobeCmd[] =
"ffprobe " // command
"-v error " // args
"-count_frames "
"-of flat=s=_ "
"-select_streams v:0 "
"-show_entries stream=nb_read_frames "
"/home/peter/DA/videos/IMG-2014-1-10-10-4-37.avi" // file
" 2>&1"; // Send stderr to stdout
FILE *pipe = popen(ffprobeCmd, "r");
if (!pipe) {
perror("Cannot open pipe.");
return 1;
}
char* buffer = new char[512];
string result;
while ((fgets(buffer, sizeof(buffer), pipe)) != NULL) {
result += buffer;
}
// See Note below
int retCode = pclose(pipe);
if (retCode != 0) {
// Program ends with error, and result has the error message
cerr << "retCode: " << retCode << "\nMessage: " << result << endl;
return retCode;
} else {
// Program ends normally, prints: streams_stream_0_nb_read_frames="xxx"
cout << result << endl;
}
delete buffer; // free memory
return 0;
}
Note
pclose is not intended to return the executed program status code, but if you need this value, pclose does it in some c++ versions/systems, so check it. Anyway it will be zero only if everything was OK.

How to read data from an open pipe: example needed

could anyone provide a small example or direct me to proper reading material in order to solve the following problem:
ls | ./myprog
What I would like to achieve is that my program reads information from ls and just print it on the screen.
I need c++ example, and if possible to do this through boost lib
thnx
P.S.
Thank you all it worked
In C, all you need to do is read the file descriptor 0:
read(0, …, …);
In C++, you can do this by using std::cin:
#include <iostream>
int main() {
std::cin >> /* a variable you want to direct the input to */
return 0;
}
That's standard C++ that is fully compatible with boost. For the way to use it, I leave it to you to read more on the manual and the plethora of examples you can find online.
for opening a file or reading from stdin you can do something in the following fashion:
shared_ptr<istream> input;
if (filename == "-" || filename == "")
input.reset(&cin, [](...){});
else
input.reset(new ifstream(filename.c_str()));
// ...
(answer copied from https://stackoverflow.com/a/2159469/1290438)
Basically, if you don't give a filename parameter, you consider data comes from stdin. That's the way cat works.
this code matches exactly your Problem:
#include <iostream>
using namespace std;
int main()
{
while (true)
{
string x;
cin >> x;
cout << x << endl;
}
}
you have to put this code into your "myprog" cpp file and then type the command you've mentioned.
It simply puts the input from the ls program to your screen

In Embedded Octave C++ how do I execute a script file? ("error: invalid call to script")

I am writing a c++ oct-file that I would like to use as a link between my c++ code and scripts that were written in Octave. I can build and execute with no problems, and as long as I am doing simple things, it seems to work. I can even call functions in a script file with feval()! I just can't seem to figure out how to execute an entire script file..
If I try this simple program, I get an error, but I'm not sure why
#include <octave/oct.h>
#include <octave/octave.h>
#include <octave/parse.h>
#include <octave/toplev.h> // for do_octave_atexit
#include <iostream>
#include <string>
using namespace std;
void runscript(const string &file) {
cout << "attempting to run: " << file << endl;
int parse_status = 0;
eval_string(file, false, parse_status);
cout << "parse_status: " << parse_status << endl;
eval_string(file, false, parse_status, 0); // I'm not sure what the difference here is or
// what the value 0 means, I can't find any documentation on
// what `hargout` is.. See Note {1} below
cout << "parse_status: " << parse_status << endl;
}
int main(int argc, char **argv) {
// Set-up
char *oct_argv[3] = {(char*)"embedded", (char*)"-q", (char*)"--interactive"};
octave_main(3, oct_argv, true);
// Attempt to run script
runscript("Script1");
runscript("Script1.m");
// `a` should be defined after running Script1.m..
octave_value_list a = get_top_level_value("a", false);
do_octave_atexit ();
return 0;
}
Script1.m is very simple and looks like this:
a = 1000;
a
When I run, I always get this output:
attempting to run: Script1
error: invalid call to script /Users/Daly/Documents/School/EECS/Labs/GitHub/deep/Octave/ Script1.m
parse_status: 0
parse_status: 0
attempting to run: Script1.m
parse_status: 0
parse_status: 0
error: get_top_level_value: undefined symbol 'a'
It only ever complains about the invalid call the first time, no matter how many times I try to eval_string or in what order.
Notes: {1} After searching for error: invalid call to script, I found this source code which at line 00155 raises this exact error if nargout isn't 0, so I thought they might be related?
But anyway, maybe this isn't the right way to be going about it. What is the correct way to execute an entire octave script from an octave-embedded c++ program? Thanks!
You should be using the function source_file() rather than eval_string(). Take a look into the parser.h file which unfortunately doesn't have a lot of comments. The names are quite self-explanatory so you shouldn't have a lot of problems.
Also, you're pretty much trying to reimplement Octave's source function. If you really want to implement it again, look into the oct-parse.cc file (generated during the build process with flex and bison).