denemo-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Denemo-devel] Embedding a script interpreter in a C program


From: Richard Shann
Subject: [Denemo-devel] Embedding a script interpreter in a C program
Date: Thu, 14 Aug 2008 11:53:13 +0100

Jeremiah,
I've have been playing around with the linking side of scripting. I have
got a tcl interpreter to fire up Denemo, but as Denemo never returns,
this is not what we want.
This seems to be a poorly documented area: we want to embed a Tcl
interpreter in our C program, not extend a Tcl interpreter with Denemo
functions.
I've found the stuff below where people are discussing this
http://wiki.tcl.tk/2074

I append the relevant bit, as there is a lot of discussion about how
confusing the earlier bit of this page is.
I'll also send you the bits I have used to hack a Tcl module that runs
Denemo, in case it may help you, but I'll put it in a separate email to
avoid confusion
Richard

stuff from the wiki.tc.tk
...
At some point in our application, we have to start up a Tcl interpreter,
and register our wrapper function with the interpreter. This is usually
done with a function called Tcl_AppInit(). Once this initialization is
complete, your application can execute scripts from strings or files by
calling Tcl_Eval() or Tcl_EvalFile().

    int Tcl_AppInit(Tcl_Interp *interp){
      if (Tcl_Init(interp) == TCL_ERROR)
        return TCL_ERROR;
      /* Now initialize our functions */
        Tcl_CreateCommand(interp, "square", _wrap_square, (ClientData) NULL, 
(Tcl_CmdDeleteProc *) NULL);
      return TCL_OK;
    }

Call this initialization function somewhere in your main line. First
create an interpreter, then call Tcl_AppInit(). You could do this all in
one fell swoop, but the Tcl_AppInit() format is standard, and supports
creating extended interpreter shells - where your application actually
becomes a Tcl interpreter, which is Extremely Cool!(tm)

    Tcl_Interp *interp;
    interp = Tcl_CreateInterp();
    Tcl_AppInit(interp);

The more modern approach to integrating Tcl applications depends on the
object interface supported in Tcl versions 8.0 and higher. The object
model supports the on-the-fly bytecode compiler, and is very efficient
for integrating C code. It is not necessary to shimmer values back and
forth to strings. Unfortunately, the object interface is a little more
complex, with special functions to convert from Tcl_Objs to basic types.
You should also do a little more careful parsing of arguments, and even
generate error messages if the Tcl command is malformed. Again, SWIG is
a great tool that can generate all this for you. But you can still do it
yourself. The new object interface function might look like this:

    static int _wrap_square(ClientData clientData, Tcl_Interp *interp, int 
objc, Tcl_Obj *CONST objv[]) {
        int  _result;
        int  _arg0;
        Tcl_Obj * tcl_result;
        int tempint;

        clientData = clientData; objv = objv;
        tcl_result = Tcl_GetObjResult(interp);
        if ((objc < 2) || (objc > 2)) {
            Tcl_SetStringObj(tcl_result,"Wrong # args. square i ",-1);
            return TCL_ERROR;
        }
        if (Tcl_GetIntFromObj(interp,objv[1],&tempint) == TCL_ERROR) return 
TCL_ERROR;
        _arg0 = (int ) tempint;
        _result = (int )square(_arg0);
        tcl_result = Tcl_GetObjResult(interp);
        Tcl_SetIntObj(tcl_result,(long) _result);
        return TCL_OK;
    }

And, you would, of course, register this new command as an object
command. The rest of the initialization remains the same

    Tcl_CreateObjCommand(interp, SWIG_prefix "square", _wrap_square, 
(ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);





reply via email to

[Prev in Thread] Current Thread [Next in Thread]