0
votes

I am working on Tcl. and using swig to extend the TCL command with C. Now, I want the extended command in C to callback the tcl procedure. But I have no idea of it.

Please help me.

First, I implement a dispatcher function in swig,which call mrecv. And in my tcl script. I call the mrecv to receive message. so, when a message arrived, i hope tcl can be notified by mrecv. that why I need find a way that invoke the callback tcl procedure from c.

And my codes is breifly is

W16 mrecv(int timeout) {
    W16 res;
    Msg_t *msg = NULL;
    APP_EVENT_T eventList[255];
    int listLength = 255;

    while (1) {
        readAgain = 0;
        msg = malloc(sizeof(Msg_t));  
        if (!msg) {
            return RETURN_ERR;
        }
        memset(msg, 0, sizeof(Msg_t));
        res = MsgRecvEvent(msg, eventList, &listLength, timeout);
        if (res == RETURN_OK) {
            msgDispatcher(msg);
        }
        free(msg);

    }                               
    return res;
 }
 void msgDispather(void *msg) {
     /*notify tcl*/
 }

and in my tcl script. I call mrecv command. tcl script:

 res [ mrecv 3000 ]

I need to know how to notify tcl.

below is my test demo.

int testCallback (char * str) {
    Tcl_Interp *interp;
    interp=Tcl_CreateInterp();
    Tcl_Eval(interp,str);
    return 0;
}

testCallback() is the extended cmd which will be called by tcl. str is the procedure name in tcl.

1
Can you make your question more specific? This is a bit too broad for StackOverflow at the moment. What have you tried so far and where are you stuck?starsplusplus
You really don't want to create interpreters very often (they're heavyweight) and they're not garbage-collected. You also probably want to use an existing one so that users can set things up before you have to actually process the callback…Donal Fellows

1 Answers

2
votes

You need to look at the Tcl_Eval family of functions which execute Tcl scripts. These take as there first parameter a pointer to the Tcl interpreter where the script is to run; and a pointer is the current interpeter is one of the parameters passed into the C function that SWIG will generate.

At present your testCallback() function creates a new Tcl_Interp and evaluates the command in that new interp. What you want to do is evaluate the command in the same Tcl_Interp that you ran the mrecv 3000 from.

In order to do this you have to convince SWIG to pass the Tcl_Interp into your mrecv function, and I think you can do this using the SWIG typemap functionality.

If you create a new typemap:

%typemap(in,numinputs=0) Tcl_Interp *interp {  
    $1 = interp;
}

and change the signature of your function to:

W16 mrecv(int timeout, Tcl_Interp *interp)

then SWIG should automatically pass the Tcl_Interp into your mrecv function without you needing to change the Tcl code.

See here for the source of the typemap and here for more information on the in typemap that makes this possible.