设为首页收藏本站

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 708|回复: 1

Combining C and tcl/tk

[复制链接]
发表于 2011-8-17 15:14:54 | 显示全部楼层 |阅读模式
Topics
Introduction
Compile Options
Initialization and Registering Commands
Accessing Variables


Introduction

Programming for X can be cumbersome, in comparison tcl/tk provides a quickand easy way of getting a graphical application up and running.  Tcl/tk isa scripting language, and as such there are some things you just can't do, orcan't do easily.  The answer is to use a hybrid of C and tcl/tk.  The tcl/tksystem comes with libraries which allow a C program to call the tcl/tk interpreter and run tcl/tk scripts.

The provided library includes methods for initializing the environment,calling different scripts, and accessing variables.  Using this hybrid environment also benefits the programmer by giving them access to featureswhich are inherent in X.  Simple call back and timer functions allow theprogrammer to schedule events, and the ability to register a C function asa procedure in tcl/tk creates a powerful tool.

This document covers the basics of integrating tcl/tk scripts with C.  

The Compile Options section describes the various librariesand include files necessary to create a program.  
The Initialization and Registering Commands section explainshow to get started, and how to call a C function from a tcl/tk script.  The last section Accessing Variables explains how to read andwrite tcl/tk variables from functions in C.



Compile Options

In order to access the tcl/tk library routines several things have to bedone to your source code and how you compile it.  There are two include fileswhich have the declarations for the calls to the library:
  1. #include <tcl.h>
  2. #include <tk.h>
复制代码

Compiling for a hybrid application requires pointing the compiler at the rightinclude directories, the right libraries, and setting the right link flags.On top of settings for tcl/tk it is also necessary to include filesand libraries for X.  

The following flags are those to be set when using g++, your own system may vary dependingon compiler and file locations.
  1. -I/software/tcl-7.4/include
  2. -I/software/tk-4.0/include
  3. -I/software/x11r5_dev/Include
  4. -L/software/tcl-7.4/lib
  5. -L/software/tk-4.0/lib
  6. -L/software/x11r5_dev/lib
  7. -ltk
  8. -ltcl
  9. -lX11
复制代码




Initialization and Registering Commands

Creating a hybrid tcl/tk & C application centres around a few choicecommands.  The first of these is the "Tk_Main" function, which is used tohand over control of the program to the tcl/tk interpreter.  This command doesnot return, so it should be the last line in your "main" function, once allof your program's initialization is done.

The "Tk_Main" function takes three parameters.  The second parameter is anarray of strings, each string having a special meaning.  The first parameter isthe number of indices in this array of strings.  The third parameter is a pointer to a function which is called for initialization.  This initializationfunction is where most of the work gets done.

The array of strings which is passed to "Tk_Main" informs the tcl/tkinterpreter of the name of the application and the location of the script whichhas the tcl/tk commands in it.  This array is actually the command lineparameters which are passed to the wish-like interpreter.  The first itemin the array gives the name of the application, and the second is the locationof the script to be run.  If the script is not in the same directory as theexecutable, it is wise to use a fully qualified path.

Due to legacy reasons, tcl/tk requires that the strings passed into mostof its functions be modifiable, it also has the occasional problem with function scope.  The easiest way to avoid these problems is to dynamicallyallocate the strings being passed in.  

The following code fragment shows acall to "Tk_Main" using the application "Hello World" and the script"hello.tcl".



  1. // prototype for the initialization function
  2. int InitProc( Tcl_Interp *interp );




  3. // declare an array for two strings
  4. char *ppszArg[2];




  5. // allocate strings and set their contents
  6. ppszArg[0] = (char *)malloc( sizeof( char ) * 12 );
  7. ppszArg[1] = (char *)malloc( sizeof( char ) * 12 );
  8. strcpy( ppszArg[0], "Hello World" );
  9. strcpy( ppszArg[1], "./hello.tcl" );




  10. // the following call does not return
  11. Tk_Main( 2, ppszArg, InitProc );

复制代码


Initialization Functions


The call to "Tk_Main" hands over control of your program to the tcl/tk interpreter, but after some base initialization is done and before the tcl/tkscript is run a user defined function can be executed.  

The above example showsa function of this type: "InitProc".  This user defined initialization functionmust return an integer and takes one parameter Tcl_Interp *, a pointer to an interpreter.

Inside of the initialization function is where you create an actual interpreter with a call to "Tk_Init".  The "Tk_Init" function takes one parameter and that is a pointer to an interpreter, this should just be the pointer passed into your initialization function.  The following code is a barebones initialization function, more will be added later.

  1.     int InitProc( Tcl_Interp *interp )
  2.     {

  3.         int iRet;

  4.         // Initialize tk first
  5.         iRet = Tk_Init( interp );
  6.         if( iRet != TCL_OK)
  7.         {

  8.             fprintf( stderr, "Unable to Initialize TK!\n" );
  9.             return( iRet );

  10.         } // end if

  11.         return( TCL_OK );

  12.     } // end InitProc
复制代码



C Functions as tcl/tk procedures

By now you are familiar with procedure calls inside of tcl/tk script.  It ispossible when programming a hybrid application to have a tcl/tk procedure calla C function.  To accomplish this requires a call to the "Tcl_CreateCommand"function.  This is normally done inside of the initialization function.  Calling the function as a procedure in tcl/tk is just like calling any otherprocedure.  No declaration for the procedure should exist in the tcl/tk script.

Functions which are to be registered as procedures have a very specific prototype.  They must return an integer, and take four arguments.  The first argument is of type "ClientData" which is a tcl/tk library type.  The second argument is a pointer to the interpreter.  The last two arguments are similarto the "argc" and "argv" arguments in a C "main" function.  These two arguments are used to pass the parameters given to the tcl/tk procedure.  The "argc"argument contains the number parameters passed to the tcl/tk procedure, andthe "argv" is an array of strings, each string containing a parameter.
  1. int Myfunc( ClientData Data, Tcl_Interp *pInterp, int argc, char *argv[] );
复制代码

When a function is registered to be used as a tcl/tk procedure it can have apointer associated with it, this pointer is passed in as the "ClientData".  Theconcept of "ClientData" allows the programmer to associate a data structurewith a tcl/tk object, and calls to procedures can reference this object.  Thisstructure is not often needed.As was mentioned earlier the registration process requires a call to the"Tcl_CreateCommand" function.  This function takes five arguments.  The first argument is a pointer to an interpreter.  The second argument is a string whichis the name of the tcl/tk procedure.  The third argument is a pointer to thefunction which is called when the tcl/tk procedure is invoked.  The last two arguments are the "ClientData" item, and a pointer to a deletion routine.  The deletion routine allows a C function to be called when the program exits in order to clean up structures associated with objects.  Like "ClientData" the pointer to the deletion function is not often necessary.  The following is a sample registration of the tcl/tk procedure called "hey_there" which is to call the above declared "Myfunc"
  1. Tcl_CreateCommand( interp, "hey_there", Myfunc, (ClientData)NULL, (Tcl_CmdDeleteProc *)NULL );
复制代码



http://fringe.davesource.com/Fringe/Computers/Languages/tcl_tk/tcl_C.html
 楼主| 发表于 2011-8-17 15:15:22 | 显示全部楼层
Accessing Variables

Being able to call a C function by invoking a tcl/tk procedure allows youto have tcl/tk get help from C.  In order to have C get help from tcl/tk there are a series of functions, the ones covered here will deal with getting information from, and putting information into a tcl/tk variable.
  
Tcl_GetVar  

The "Tcl_GetVar" function returns a pointer to a string which contains the contents of the specified tcl/tk variable.  The function takes three arguments,a pointer to the interpreter, a string with the name of the tcl/tk variable,and a flag.  The variable that is accessed is at the current scope in theexecuting script associated with the interpreter.  If there is no variable atthe current scope level with the given name then global variables are checked.If no matching global variable is found an error is returned.  The flags argument allows you to specify TCL_GLOBAL_ONLY, in order to force the functionto only check for global variables with the given name.  The following codeis part of a tcl/tk script that will be accessed.
  1. set say_hello_to "World"
复制代码

The following code is a the call in C to access the tcl/tk variable "say_hello_to".
  1.     char sHelloTo[30];

  2.     // after this call sHelloTo should contain "World"
  3.     strncpy( sHelloTo, Tcl_GetVar( pInterp, "say_hello_to", 0 ), 29 );

复制代码

Tcl_SetVar  

The "Tcl_SetVar" function allows the programmer to change the contents ofa tcl/tk variable.  The function takes four arguments, the first is a pointerto the interpreter, the second a string indicating the name of the tcl/tkvariable to change, the third is a string with the new value for the variable, and the last argument is for flags.  The "Tcl_SetVar" flags are thesame as for "Tcl_GetVar".  The "Tcl_SetVar" function returns NULL if an erroroccurred during the setting.  If the variable does not exist, this functionwill create the variable locally to the scope currently in execution in thescript referenced by the interpreter pointer.  The following code sets a tcl/tk variable called "say_hello_to" to contain the value "World".
  1. Tcl_SetVar( pInterp, "say_hello_to", "World", 0 );
复制代码


您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|小黑屋|BC Morning Website ( Best Deal Inc. 001 )  

GMT-8, 2025-8-26 09:23 , Processed in 0.019149 second(s), 16 queries .

Supported by Best Deal Online X3.5

© 2001-2025 Discuz! Team.

快速回复 返回顶部 返回列表