I start interactive tcl interpreter by calling Tcl_main() and take some tcl commands there. After that, I want to quit tcl interpreter and resume my program. However, when I type "exit", it will exit the whole program. Is there a way to exit tcl interpreter and continue my program ? Thanks.
The Tcl_Main() function does not provide any way for code to resume after it finishes; it's a convenience wrapper for handling simple programs so that you don't have to worry about such things, but that wrapper is limited in a number of ways, and one of those is that you can't do what you're seeking to do. (At the end of the function, it calls Tcl_Exit().)
But you don't need to use Tcl_Main()! It just uses Tcl's public API (with a few exceptions that probably don't matter for you). You can duplicate everything by calling (approximately):
Tcl_FindExecutable(argv[0]); // ONCE PER PROCESS; INITIALISES TCL C LIBRARY
Tcl_Interp *interp = Tcl_CreateInterp();
// ... now in your loop evaluate code, perhaps from the user ...
Tcl_Eval(interp, "some code here");
// ...
Tcl_DeleteInterp(interp);
// Carry on as normal
There's no great magic in there. Just initialise the library, create an interpreter, evaluate your code in there (perhaps after getting it from the user; invent your own reader loop if you want or code it up in Tcl), and then delete the interpreter when you're done.
Related
I'm working on a WebApi project written in F#. Here a snippet:
module MyModule
open System
let MyGuid = Guid.Parse "934F0B12-D00A-491D-862D-EE745EF3C560"
let myFunction list =
list.Get(MyGuid) // --> here MyGuid has the TypeInitializationException before list.Get is called
By debugging I can see that the MyGuid actually has an error
Changing the code followings, it works:
module MyModule
open System
let MyGuid () = Guid.Parse "934F0B12-D00A-491D-862D-EE745EF3C560"
let myFunction list =
list.Get(MyGuid())
I actually know the MyGuid of the first example is a variable and the second one a function definition, but why does the first rise the exception? I my code MyGuid is used some times. so in the first example I'd have only one instance, in the second a new instance every time MyGuid is called...
I'm not 100% sure that this is the problem here, but I've seen similar behaviour when using unit test runners sometimes. My guess is that the error happens because the top-level MyGuid variable is not initialized correctly and has the default zero value (and as a result, the lookup fails).
The way global variables are initialized in F# is tricky - if you compile code as executable, this can happen from the Main method. But if you compile code as a library, the compiler inserts an initialization checks into static constructors of the types in your library (to make sure everything is initialized before you access anything).
I think this can break if you compile your code as an executable, but then load it as a library - the entry-point is not called and so the variables are not initialized. I'm not sure how exactly WebApi loads libraries, but this could be a problem - especially if you compile the F# code as an executable.
Your workaround of turning the global variable into a function fixes this, because the function is compiled as a method and so you avoid referring to an uninitialized value. Sadly, I don't think there is a better workaround for this.
I'm trying to draw on a canvas that is in the top level of my Tcl/Tk script, but from inside a call by fileevent like this:
canvas .myCanvas {}
proc plot_Data { myC inp } { $myC create rectangle {} }
fileevent $inp readable [list plot_Data .myCanvas $inp ]
pack .myCanvas
I have found out that the script called by fileevent (plot_Data) lives in a different space.
The script for a file event is executed at global level (outside the context of any Tcl procedure) in the interpreter in which the fileevent command was invoked.
I cannot make the two meet. I have definitely narrowed it down to this: plot_Data just can't access .myCanvas . Question: How can the fileevent script plot on the canvas?
The goal of this is live plotting, by the way. $inp is a pipe to a C-program that reads data from a measurement device. It is imho rightly configured with fconfigure $inp -blocking 0 -buffering none.
Callback scripts (except for traces, which you aren't using) are always called from the context of the global namespace. They cannot see any stack frames above them. This is because they are called at times that aren't closely controlled; there's no telling what the actual stack would be, so it is forced into a known state.
However, canvases (and other widgets) have names in the global namespace as well. Your callbacks most certainly can access them, provided the widget has not been destroyed, and might indeed be working. You just happen to have given it an empty list of coordinates to create, which is not usually legal to use with a canvas item.
Since you are using non-blocking I/O, you need to be aware that gets may return the empty string when reading an incomplete line. Use fblocked to determine if a partial read happened; if it does, the data is in a buffer on the Tcl side waiting for the rest of the line to turn up, and it is usually best to just go to sleep and wait for the next fileevent to fire.
A problem that might bite you overall is if the C program is in fully buffered mode; this is true by default when writing output from C to a pipe. Setting the buffering on the Tcl side won't affect it; you need to use setvbuf on the C side, or insert regular fflush calls, or use Expect (which pretends to be an interactive destination, though at quite a lot of cost of complexity of interaction) or even unbuffer (if you can find a copy).
I have a C shell that usually calls Tcl routines using Tcl_Eval. Normally I was fine with just executing what the user typed and getting some status as a result. However, now I need to receive the actual stdio output from the command that user typed. Is there any way to get it using the Tcl C procedures?
As a side note: I need to figure out the list of current procedures available in the Tcl interpreter, both built in and user sourced. Basically, the output from info procs *.
I think you could go like this:
Create a pipe by calling pipe(2).
Then in your interp:
Close stdout by calling Tcl_Close() on it.
Turn the write-end file descriptor of your pipe into Tcl's stdout channel by calling Tcl_MakeChannel() right after closing stdout.
Or use just replace the stdout with a call to Tcl_SetStdChannel().
Process the data coming from the pipe.
As to your side note — I think you could just call Tcl_Eval() in your interpreter and process the returned list using the list-processing functions from the Tcl API.
Update (from one of my comments): after some more thought I think it might be possible to just create a custom Tcl channel which implementation would just save away the data written to it and then register an instance of such a channel as stdout. See Tcl_CreateChannel() and Tcl_RegisterChannel().
On C project I currently work at there is much code that uses goto and break for error handling. Break and goto are usually found inside
if (error_occured) {
LOGGER_REPORT_ERROR();
goto cleanup;
}
I tried extracting code that includes chunks like this with Eclipse CDT refactoring but it did not work automatically.
This should be theoretically possible to do this automatically if additional error code variable is created in original function and extracted function returns error code somehow.
Is there an IDE or IDE plugin for automatic refactoring that supports such function extractions already?
Say I have below lines any in a Java class,
System.out.println("start");
if(true)//The compiler will give compile time error if I uncomment this.
throw new RuntimeException();
System.out.println("end");
The unreachable code error message will appear if the if(true) is commented. Why Don't the compiler know that the line under if(true) will always be executed?
Is the Java compiler is designed to work like this or is it a limitation?
It's deliberate part of the design around code reachability. See section 14.21 of the JLS which has a section at the bottom about this.
The rationale for this differing treatment is to allow programmers to define "flag variables" such as:
static final boolean DEBUG = false;
and then write code such as:
if (DEBUG) { x=3; }
The idea is that it should be possible to change the value of DEBUG from false to true or from true to false and then compile the code correctly with no other changes to the program text.
It is a limitation of how far you go to check you have dead code or code which will never run.
The JVM can detect the code is dead and not compile it.