1

I'm trying to run a tcl script from some specific path on my PC from a C++ program. Unfortunately, I do not have any idea how to do so. Please advise how I can execute a tcl script from a C++ program. An example would be appreciated. For now, I have tried using the Tcl_Eval command.

3
  • 1
    Hello, your question is a bit broad and it is hard to know what you have tried? I would help if you could show us some (working) code, with an explanation of how it does not achieve what you want. Commented May 24, 2020 at 13:56
  • For example, it would be helpful to know if you are trying to fork a new process and run the script in the new process or if you want the script to run within the existing C++ program. Commented May 24, 2020 at 16:10
  • Hi, I'm trying to run CPP script, at some point in the run, i want that the CPP test call a tcl script for run in, I have try this one - (Tcl_EvalFile(pInterp, "tclsh {\"C:/Users/avi/Desktop/Temp/test.tcl"}")); were not working for me. in addition, invoke a tcl shell and send a command that run the tcl scripts could be a good solution for me. thanks Commented May 24, 2020 at 16:22

1 Answer 1

1

Depending on what you exactly want to do, you either run the Tcl script as a subprocess or embed a Tcl interpreter instance and use that. I'll assume that it is the latter.

Tcl is, apart from everything else, a (mainly) C library (and its header file is intentionally made compatible with being used from both C++ and Objective C). Thus:

#include <tcl.h>
#include <stdexcept>
#include <string>

public class TclInterpreter {
private:
    Tcl_Interp *interp;
public:
    TclInterpreter(const char *argv0 = nullptr) : interp(nullptr) {
        static bool initLib;
        if (!initLib) {
            Tcl_FindExecutable(argv0);
            initLib = true;
        }
        interp = Tcl_CreateInterp();
        if (!interp) throw new std::runtime_error("failed to initialise Tcl library");
    }

    ~TclInterpreter() {
        if (interp) Tcl_DeleteInterp(interp);
    }

    std::string evalFile(const std::string &filename) {
        // This next line is the CRITICAL one!
        int code = Tcl_EvalFile(interp, filename.c_str());

        if (code >= TCL_ERROR) {
            // You should make your own exception, but I've lost patience typing it out
            // This throws the exception message; it lasts until you use the interpreter again
            throw Tcl_GetStringResult(interp);
        }
        return std::string(Tcl_GetStringResult(interp));
    }
}

You'd then be able to call that a bit like this:

TclInterpreter interpreter(argv[0]); // << omit ‘argv[0]’ if you don't know it
std::string filename("my_file.tcl");
std::string result = interpreter.evalFile(filename);
std::cout << result << '\n';

You'd need to make sure that tcl.h is found when compiling, and you'd need to make sure that you link against libtcl.so/libtcl.dll/libtcl.dylib when linking. (The exact filename to link against may depend on exactly which version of Tcl you're wanting to link and what OS you're on.)


For a more sophisticated version of this that probably does a lot better job of error handling — the part I've sort-of glossed over rather above! — among other things (but is consequently more work to understand), see C++/Tcl. However, that doesn't seem to expose an evalFile method at this point so you'd need to run source my_file.tcl as a little scriptlet. (Tcl_EvalFile() is basically the implementation of the Tcl source command.)

Sign up to request clarification or add additional context in comments.

1 Comment

Standard Tcl's API will remain strict C. Not a chance of us changing that. We might use other languages in the implementation where that simplifies things for us.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.