简体   繁体   中英

C++ executing a code from a text file

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

  1. Read sample.txt into memory.
  2. Compile it to a function.
  3. Call the function.

Some possibly-helpful links:

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> 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM