分享
 
 
 

TCL/TK 与 C 程序的集成

王朝c/c++·作者佚名  2006-11-24
窄屏简体版  字體: |||超大  

文章摘要:

本文覆盖了 [url=http://www.pccode.net].net/showsoftd.php?ID=282"TCL/TK 脚本与C 集成的一些基础知识。

一、 简介

比较 [url=http://www.pccode.net].net/showsoftd.php?ID=282"TCL/TK 提供的快速而又容易的开发图形拥护界面,X 程序显得很烦琐。 [url=http://www.pccode.net].net/showsoftd.php?ID=282"TCL/TK 是一种脚本语言,就象其它的一些脚本语言一样,也有很多事情不能够做或很难做。解决途径是联合 C 与 tcl/tk 一起来开发. [url=http://www.pccode.net].net/showsoftd.php?ID=282"TCL/TK 系统提供C 程序调用TCL/TK 的解释器来运行TCL/TK脚本。提供的库包括初始化变量的方法,调用不同的脚本和访问变量。利用这些混合变量对它们访问X固有的特性也提供了好处。简单的回调和时间函数允许程序员制定事件,注册一个C函数为TCL/TK的过程的能力成为一个强大的工具。这篇文档覆盖了TCL/TK脚本与C 集成的一些基础知识。编译选项部分描述了变量库并包含了建立程序的必要文件。 初始化与注册名令部分解释了怎样开始,怎样从TCL/TK脚本中调用C函数,最后一部分访问变量阐述了怎样来从C函数里来读与写TCL/TK变量。

二、编译选项

为了能访问TCL/TK 库,必须在你的源代码中要设置一些常规的例程做并编译它。有两个调用库的头文件被声明。

#include

#include

编译混合应用程序需要指出正确的编译目录,正确的库,并设置正确的连接标志。在TCL/TK顶部的设置也是必须要包含的文件。而下面的设置是在使用 g++ 时要设置的。你的系统依赖于编译器和文件的定位可能有不同的变化。

-I/software/tcl-7.4/include

-I/software/tk-4.0/include

-I/software/x11r5_dev/Include

-L/software/tcl-7.4/lib

-L/software/tk-4.0/lib

-L/software/x11r5_dev/lib

-ltk

-ltcl

-lX11

三、初始化与注册命令

建立混合 tcl/tk & C 应用程序的中心要围绕几条选择命令。

首先就是"Tk_Main" 函数, 它用来控制整个 tcl/tk 解释器程序。这条命令没有返回值,因此,它需在你的"main" 函数中加下划线,你所有程序的一旦初始化,"Tk_Main" 函数带来三个变量。第二个变量是一个字符串型数组,每个字符串都有一个特殊的含义。第一个变量表示在这个数组的元素个数。第三个变量是指向初始化函数的指针。此初始化函数在许多地方都要被执行。字符串数组通过"Tk_Main"来通知tcl/tk解释器应用程序的名称和tcl/tk 命令在脚本中的位置。这个数组实际上是传给解释器的命令行参数。数组的第一项给出应用程序名称,第二项给出了运行的脚本位置。如果脚本没有在相同的执行目录下,则需要完整路径。由于继承原因,tcl/tk 需要字符串在许多函数里可以修改,它也有函数作用范围的问题,避免这些问题最早的办法是传递时动态分配字符串下面的代码碎片显示了调用 利用"Hello World" 应用程序和脚本"hello.tcl"来调用 "Tk_Main"。

// prototype for the initialization function

int InitProc( Tcl_Interp *interp );

// declare an array for two strings

char *ppszArg[2];

// allocate strings and set their contents

ppszArg[0] = (char *)malloc( sizeof( char ) * 12 );

ppszArg[1] = (char *)malloc( sizeof( char ) * 12 );

strcpy( ppszArg[0], "Hello World" );

strcpy( ppszArg[1], "./hello.tcl" );

// the following call does not return

Tk_Main( 2, ppszArg, InitProc );

初始化函数

"Tk_Main" 的调用控制了你的程序在tcl/tk中的整个调用,但是在底部初始化之后和tcl/tk 脚本运行之前,能够执行用户自定义的函数。上面的例子中展示了这个类型的函数: "InitProc". 用户定义的初始化函数必须要返回一个整数类型并产生一个指向解释器的参数Tcl_Interp *。在初始化函数里面建立实际解释器调用"Tk_Init"。"Tk_Init"函数设置一个指向解释器的参数,这正是传递到初始化函数的指针。下面的代码仅只是初始化函数,更多的则是在后面列出。

int InitProc( Tcl_Interp *interp )

{

int iRet;

// Initialize tk first

iRet = Tk_Init( interp );

if( iRet != TCL_OK)

{

fprintf( stderr, "Unable to Initialize TK!n" );

return( iRet );

} // end if

return( TCL_OK );

} // end InitProc

C函数作为 tcl/tk 过程

现在你要熟悉在tcl/tk 脚本中的过程调用。当设计混合应用程序中有tcl/tk的过程调用C函数是可能的。完成它需要调用"Tcl_CreateCommand" 函数。这是在初始化函数里的常用做法。在tcl/tk 过程中调用函数就象调用其它的过程一样。在tcl/tk 脚本中存在就不必声明这个过程。函数注册有一个特定原型的过程。它们必须要返回一个整数类型,并设置4个变量,第一个是tcl/tk库文件类型"ClientData"。第二个变量是指向解释器的指针。最后的两个变量类似于在C "main"函数中的 "argc" 和 "argv" 这两个变量被用于传递参数给tcl/tk 过程。参数"argc" 包含了传递给tcl/tk过程的参数个数"argv" 是字符串数组,每个字符串包含了一个参数。

int Myfunc( ClientData Data, Tcl_Interp *pInterp, int argc, char *argv[] );

当一个函数被注册作为tcl/tk 过程使用时需一个指针与之联系,指针通过"ClientData"来传递进来。"ClientData"的概念允许程序员联系数据结构和对象,调用能引用这个对象的过程。这个结构不经常需要。象早先提到的注册过程需要调用"Tcl_CreateCommand" 函数。这个函数有5个参数。第一个参数是指向解释器的指针,第二个参数是在tcl/tk 中的过程名,第三个参数是一个指向函数的指针,它在当tcl/tk过程被执行时调用。最后两个参数是 "ClientData" 项, 一个指针删除例程。它允许C函数在程序退出为了清空联系对象的结构时被调用。象指向删除函数的指针"ClientData"不经常调用。下面是tcl/tk 过程调用"hey_there" 来调用上面声明的"Myfunc"进行注册的例子。

Tcl_CreateCommand( interp, "hey_there", Myfunc, (ClientData)NULL,

(Tcl_CmdDeleteProc *)NULL );

变量访问

在执行tcl/tk过程时能调用C函数并允许你从C中获得tcl/tk的帮助,为了从tcl/tk 中获得C的帮助,这有一系列函数,其中包含了从tcl/tk变量中处理获得的信息和设置的信息。

Tcl_GetVar

"Tcl_GetVar" 函数返回一个指向tcl/tk变量的字符串指针。这个函数有三个参数:指向解释器的指针,tcl/tk 变量的名称,一个标志flag。这个变量在执行脚本联系到解释器的当前范围被访问。如果在当前范没有局部变量则访问全局变量。如没有匹配的全局变量存在则返回一个错误。 Flags参数允许你指定TCL_GLOBAL_ONLY, 为了使这个函数仅仅访问此变量名的全局变量,下面是tcl/tk 脚本中被访问的一部分代码。

set say_hello_to "World"

下面的代码是在C里访问tcl/tk变量"say_hello_to".

char sHelloTo[30];

// after this call sHelloTo should contain "World"

strncpy( sHelloTo, Tcl_GetVar( pInterp, "say_hello_to", 0 ), 29 );

Tcl_SetVar

"Tcl_SetVar"函数允许程序员修改tcl/tk变量的值。此函数有四个参数:第一个是解释器指针,第二个是要修改值的tcl/tk变量名称,第三个是要修改的新值,最后一个是tcl/tk标志flags。"Tcl_SetVar" 的标志flags跟"Tcl_GetVar"的相同。当设置期间遇到出错时"Tcl_SetVar"函数返回NULL值。如果变量不存在,则此函数将在解释器指针引用的脚本内建立一个新的变量。下面的代码将设置tcl/tk变量"say_hello_to"的值为"World"。

Tcl_SetVar( pInterp, "say_hello_to", "World", 0 );

集成C & tcl/tk 应用程序的例子

这个应用程序展示了集成C和TCL/TK所需要的基础。此应用程序展示了一系列的登录框和按钮。当信息从登录框输入和按钮被按下时,其他的空域也被相应的更新。这有许多分享内存设备的接口,是调用大型应用程序的方法。这个接口需要头文件在下面没有包含进来,因此不修改而编译此应用程序是不可能的。但就阅读来说这并不是一个坏的示例。

The Makefile

The script file: pr1

The C file: proof.c

#!/.software/local/.admin/bins/bin/wish -f

#============================================================

# xmail

# by Christopher Trudeau, Copyright 1997

#

# This tcl/tk script displays a desktop clock which goes inverse video when

# new mail arrives. A pull down menu allows the user to launch remote login

# sessions on servers specified in the "hosts" variable. The sessions have

# the appropriate "xhost" and "DISPLAY" values.

#

# Comments and criticism on this program are greatly appreciated. Feel free to

# send me a note at ctrudeau@etude.uwaterloo.ca. This material is copyright

# but non-commercial institutes have permission to reproduce the program in

# its entirety, all other uses require explicit written permission of the

# author.

#============================================================

#------------------------------------------------------------

# Global Settings

#-----------------------------------------------------------

# fill in the following list for hosts that you wish to access, spaces or tabs

# separating the names of the hosts; eg:

#

# set hosts "ampere etude watt.uwaterloo.ca"

set hosts "ampere watt ohm morse novice"

#------------------------------------------------------------

# Procedures

#-------------------------------------------------------------

# proc prRefreshDisplay - called periodically to refresh the displayed time and

# status of the mail box

proc prRefreshDisplay {} {

global last

# get the time

set i [exec date]

set i [ string range $i 11 15 ]

# get the mailbox status

catch {[exec frm -q -s new]} mail

if { [string first "no" $mail] == -1 } {

# "You have new mail." results in white on black

.lTime configure -fg white -bg black -text $i

# if first time set, do the double beep thing

if { $last == 0 } {

bell

after 120

bell

}

set last 1

} else {

# "You have no new mail." results in black on white

.lTime configure -fg black -bg white -text $i

set last 0

}

after 15000 prRefreshDisplay

}

#------------------------------------------------------------

# Main Code

#------------------------------------------------------------

# create the main window and place it if specified

wm title . "xmail"

set args [lindex $argv 0]

string trim $args -if

{ $args == "geometry" } {

wm geometry . [lindex $argv 1]

}

# figure out what terminal name we are at

set userName [exec whoami]

set termName [exec who ]

set temp [string first $userName $termName]

set termName [string range $termName $temp end]

set temp [string first ( $termName]

set temp2 [string first ) $termName]

set termName [string range $termName $temp $temp2]

set termName [string trim $termName "()"]

# initialize variables and widgets

set last 0

set font "-*-*-medium-r-normal--*-120-*-*-*-*-*-*"

set font2 "-*-*-medium-r-normal--*-100-*-*-*-*-*-*"

label .lTime -font $font

# create the menu button

menubutton .mMenu -relief raised -font $font2 -text ">" -menu .mMenu.m

menu .mMenu.m -tearoff 0

.mMenu.m add cascade -label "xterms" -menu .mMenu.m.xterms

#create the sub menu "xterms"

menu .mMenu.m.xterms -tearoff 0

.mMenu.m.xterms add command -label "local" -command {exec xterm -title local &}

set count 0

set hostN [lindex $hosts $count]

while { $hostN != "" } {

catch { exec xhost $hostN }

set cmd "exec rsh $hostN xterm -display $termName:0 -title $hostN &"

.mMenu.m.xterms add command -label $hostN -command $cmd

incr count 1

set hostN [lindex $hosts $count]

}

.mMenu.m add separator

.mMenu.m add command -label "Exit" -command exit

pack .lTime .mMenu -side left

prRefreshDisplay

#-----------------------------------------------------------

CC = gcc

DEPEND = makedepend

TCL_DIR = /software/tcl-7.4

TK_DIR = /software/tk-4.0

INCS = -I$(TCL_DIR)/include -I$(TK_DIR)/include -I/software/x11r5_dev/Include

LIBS = -L/software/x11r5_dev/lib -L$(TCL_DIR)/lib -L$(TK_DIR)/lib

CCFLAGS= $(INCS) $(LIBS) -g -Wall

LFLAGS = -ltk -ltcl -lX11 -lsocket -lm

ALLDEFINES = -DDEBUG

.SUFFIXES: .c .o .cpp

.c.o:

$(CC) $(CCFLAGS) $(ALLDEFINES) -c $<

.cpp.o:

g++ -g -Wall $(ALLDEFINES) -c $*.cpp

PROOF_C = proof.c

PROOF_O = proof.o

all: proof

proof: &

[1] [2] 下一页

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有