Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations gkittelson on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Tcl/C example test problem

Status
Not open for further replies.

fabien

Technical User
Sep 25, 2001
299
AU
Hi!

I found the following examples on the net. This is to learn how to link Tcl and C. First the example.c would not compile because Tk_CreateMainWindow does not seem to exist anymore in 8.4. So I replaced it with Tk_MainWindow which worked for the compiler (CC from Sun) but when I run it it gives me a bus error. Can somebody explain me why?

Many thanks!



------------ example.tk --------------
# example.tk
# Demonstrates Tcl/Tk and C interaction while doing something useful!
# Originally written entirely in Tcl/Tk but added C calls as a demo.

# 20 Feb 1995 - R. Hagen rhagen@awi-bremerhaven.de

# -------------------------------------------------
# A simple decimal degree to deg,min,sec converter
# -------------------------------------------------

# -------------------------
# set up the user interface
# -------------------------
label .title -text "Lat/Lon Converter"

frame .convert

label .deglabel -text "degrees "
label .minlabel -text "minutes "
label .seclabel -text "seconds "
label .deg -width 5 -relief sunken -bd 2 -bg LightGoldenrod1 \
-textvariable degrees
label .min -width 6 -relief sunken -bd 2 -bg LightGoldenrod1 \
-textvariable minutes
label .sec -width 6 -relief sunken -bd 2 -bg LightGoldenrod1 \
-textvariable seconds
label .eqlabel -text " = "
entry .decdeg -width 11 -relief sunken -bd 2 -bg PowderBlue \
-textvariable decDegrees



# --------------------------------------------
# Make the return key execute the calculations
# --------------------------------------------
bind .decdeg <Return> {okCommand}

# ------------------
# Set up the buttons
# ------------------
frame .bframe
button .okbutton -text OK -command {okCommand}
button .exitbutton -text Exit -command exit
button .clearbutton -text Clear -command clearCmd
radiobutton .ddm -text &quot;deg + decimal min&quot; -variable mode -value 0 \
-anchor w
radiobutton .dms -text &quot;deg + min + sec&quot; -variable mode -value 1 \
-anchor w

# ---------------
# Pack everything
# ---------------
pack .title -side top
pack .convert -side top -padx 2m -pady 2m
pack .decdeg .eqlabel .deg .deglabel .min .minlabel .sec .seclabel \
-in .convert -side left
pack .bframe -side top
pack .okbutton .exitbutton .clearbutton -in .bframe -side left -padx 2m
pack .ddm .dms -in .bframe -side right -padx 2m

# -------------------------------------------------
# set the initial focus to the decimal degree entry
# -------------------------------------------------
focus .decdeg

# -------------------
# initialize the mode
# -------------------
set mode 1

# ------------------------------------
# Procedure to execute the decimal to deg min sec calculation
# here we do the calculation in C as an example.
# Also as an example we return the data in two ways, by having
# the C program reach in and directly change the degrees value,
# and by returning the minutes and seconds data in the result.
# ------------------------------------
proc okCommand {} {
global degrees minutes seconds decDegrees mode

if {$decDegrees != &quot;&quot;} {

# call the C routine, returning data in degList. We return
# deg min sec, but degrees was already set by the C routine
# and is already displayed, so we ignore the returned value.

set degList &quot;[eval calculate $decDegrees]&quot;
set minutes [lindex $degList 1]
set seconds [lindex $degList 2]

if {$mode == &quot;0&quot;} {
set minutes [format &quot;%6.3f&quot; [expr $minutes + ($seconds / 60)]]
set seconds &quot;&quot;
}
}
}

# ------------------------------
# Procedure to clear all entries
# ------------------------------
proc clearCmd {} {
global degrees minutes seconds decDegrees

foreach thing {degrees minutes seconds decDegrees} {

set $thing &quot;&quot;
}
}

-------------example.c------------------

/* example.c
Demonstrates Tcl/Tk and C interaction.
The main() routine below was pretty much copied from the draft of the
Brent Welch book &quot;Practical Programming in Tcl and Tk&quot;

20 Feb 1995 - R. Hagen rhagen@awi-bremerhaven.de
*/

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <tcl.h>
#include <tk.h>

#define TCLGO TCL_GLOBAL_ONLY

/* Here we define a C function to be called as a Tcl command */
static int calculate(ClientData dummy, Tcl_Interp* interp, int argc,
char* argv[])
{
int degPart, minPart;
float decimalDegrees, fractionPart, decimalMinutes, decimalSeconds;
char temp[12] = {0};

if(argc != 2) return ;

decimalDegrees = atof(argv[1]); /* argv[1] contains value passed
from Tcl */
degPart = (int) decimalDegrees;
fractionPart = fabs(decimalDegrees - degPart);
decimalMinutes = fractionPart * 60.0;
minPart = (int) decimalMinutes;
fractionPart = decimalMinutes - minPart;
decimalSeconds = fractionPart * 60.0;

/* we must convert our ints and floats to strings for Tcl using sprintf
*/
sprintf(temp,&quot;%d&quot;,degPart);
Tcl_SetVar(interp, &quot;degrees&quot;,temp,TCLGO); /* set the tcl variable */
Tcl_AppendElement(interp, temp); /* append to the result string
*/
sprintf(temp,&quot;%d&quot;, minPart);
Tcl_AppendElement(interp, temp); /* append to the result string
*/
sprintf(temp,&quot;%6.3f&quot;, decimalSeconds);
Tcl_AppendElement(interp, temp); /* append to the result string
*/

return TCL_OK;

}

int Example_Init(Tcl_Interp* interp)
{
/* Here we tell the Tcl interpreter about our calculate C function
and &quot;link&quot; it to a Tcl name. Here the C and Tcl names are the same
but it is not required.

Tcl name C name */
Tcl_CreateCommand(interp, &quot;calculate&quot;, calculate,(ClientData) 0,
(void (*)()) NULL);

return TCL_OK;
}



main(int argc, char *argv[])
{
Tcl_Interp *interp;
Tk_Window mainWindow;
int error;
char *trace;

/* first we create a Tcl interpreter */

interp = Tcl_CreateInterp();

/* now we create a Tk main window */

mainWindow = Tk_CreateMainWindow(interp, getenv(&quot;DISPLAY&quot;),
&quot;example&quot;,&quot;Tk&quot;);

if(mainWindow == NULL) {
fprintf(stderr, &quot;%s\n&quot;, interp->result);
exit(1);
}

/* now we initialize our interpreter for Tcl,Tk,and our personal
example C commands */

if(Tcl_Init(interp) != TCL_OK) {
fprintf(stderr, &quot;Tcl_Init failed: %s\n&quot;, interp->result);
}
if(Tk_Init(interp) != TCL_OK) {
fprintf(stderr, &quot;Tk_Init failed: %s\n&quot;, interp->result);
}
if(Example_Init(interp) != TCL_OK) {
fprintf(stderr, &quot;Example_Init failed: %s\n&quot;, interp->result);
}

/* now we tell the interpreter which Tcl/Tk file to use */

error = Tcl_EvalFile(interp, &quot;example.tk&quot;);
if(error != TCL_OK) {
fprintf(stderr, &quot;%s: %s\n&quot;, &quot;example.tk&quot;, interp->result);
trace = Tcl_GetVar(interp, &quot;errorInfo&quot;, TCL_GLOBAL_ONLY);
if(trace != NULL) {
fprintf(stderr, &quot;*** TCL TRACE ***\n&quot;);
fprintf(stderr, &quot;%s\n&quot;, trace);
}
}

/* finally we enter the event loop and wait for user input */

Tk_MainLoop();
}


 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top