Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

how to write inputproc for a custom channel type that serves as stdin

28 views
Skip to first unread message

ratchet

unread,
Oct 14, 2017, 4:04:21 PM10/14/17
to
I am using the C API to embed an interpreter into a C++ game that uses the SDL2 library. My overall strategy for getting user input into the interpreter is as follows:

I have a custom channel type that I use to create a channel, and I make this stdin for the interpreter with Tcl_SetStdChannel. I use SDL2 fucntions to collect keyboard events into a C++ string. When the user hits Enter, I call Tcl_NotifyChannel to try to read input. I use the StdinProc from tclMain.c as my channel handler. This function makes a call to Tcl_Gets which invokes my inputproc function from my custom channel. The inputproc puts the c++ string into the buf, like this (input is the string I want to read in):


static int
inputproc(ClientData instancedata, char *buf, int toRead, int *errorCodePtr) {
InteractiveState* is = (InteractiveState* ) instancedata; //not used
if (input == "") { // blocked!
return EAGAIN;
}
input.copy(buf, input.size());
int read = input.size();
input = "";
return read;


}

This works fine for most things, but if I try to interpret a command like "gets stdin name" there are problems. The command causes inputproc to run again, but there is no new input yet, so it returns EAGAIN. However when the user puts in another string, this is not used to set the value of "name." When I watch the "buf" and "toRead" variables while debugging, I see some interesting behavior that I don't understand. toRead is smaller by the length of "gets stdin " and the text "name\n" is in "buf" when inputproc is called.

I am not sure that the trouble I am having is really in my implementation of inputproc and not a more general failure to understand how to embed the interpreter.

I am having a lot of trouble finding code examples of how to write inputproc for a custom channel. (there are helpful examples for making a custom stdout and stderr, but not for stdin)

Thanks in advance for any help.

Ralf Fassel

unread,
Oct 16, 2017, 4:25:51 AM10/16/17
to
* ratchet <dave...@gmail.com>
Haven't checked all the prerequisities, but:

| static int
| inputproc(ClientData instancedata, char *buf, int toRead, int *errorCodePtr) {
| InteractiveState* is = (InteractiveState* ) instancedata; //not used
| if (input == "") { // blocked!
| return EAGAIN;
| }
| input.copy(buf, input.size());

I'd say you should copy no more than 'toRead' bytes here instead of
input.size(), since 'buf' might not be able to hold more than that, and
you create a buffer overrun if "toRead < input.size()".
Not sure whether this is related to your problem, though.

| This works fine for most things, but if I try to interpret a command
| like "gets stdin name" there are problems. The command causes
| inputproc to run again, but there is no new input yet, so it returns
| EAGAIN. However when the user puts in another string, this is not used
| to set the value of "name." When I watch the "buf" and "toRead"
| variables while debugging, I see some interesting behavior that I
| don't understand. toRead is smaller by the length of "gets stdin " and
| the text "name\n" is in "buf" when inputproc is called.

Could be that the first round did not ask for *all* input, but only a
part of it, but you already have read all of it.

HTH
R'
0 new messages