varun kumar
varun kumar

Reputation: 151

Calling a procedure from another script without sourcing Tcl

I have some doubts regarding Tcl scripting. Is it possible to call a procedure in one file to another without sourcing the file which contain procedure?

Upvotes: 1

Views: 1576

Answers (2)

Schelte Bron
Schelte Bron

Reputation: 4813

You can use the autoload functionality of Tcl. The standard way is to put the file(s) with your procedures somewhere under one of the directories listed in the auto_path variable. Then run the auto_mkindex command on this directory and files. That will create a file called tclIndex in the directory.

You can then just use the procedures in your scripts and they will automatically be loaded when used.

If you want, you can get much more creative. Basically the autoload functionality looks for an element with the name of the procedure in the auto_index array. The value of the array element is expected to be a command that will be executed and should result in the procedure (or command) being created.

Example: Let's suppose /usr/share/tcl is in your auto_path (you can also use a directory that is not in auto_path by default, but then you have to add it at the start of each script). You create a directory under /usr/share/tcl named helpers. In that directory you create files with some commands you like to be available to all of your scripts. Like a file called cat.tcl:

proc cat {filename} {
    if {[catch {open $filename} fd opts]} {
        return -options [dict incr opts -level] -errorinfo "" $fd
    }
    try {
        return [read -nonewline $fd]
    } finally {
        close $fd
    }
}

Then you start a tclsh (for the indicated directory you probably need to do this as root) and run the following command:

auto_mkindex /usr/share/tcl helpers/*.tcl

This creates a file called tclIndex in /usr/share/tcl. From that point on, you can just use the cat command in any Tcl session or script:

cat /etc/motd

Upvotes: 1

Donal Fellows
Donal Fellows

Reputation: 137567

Something has to source the code to make it executable, but it doesn't always have to be your current process. You can easily write a separate script to source and run that procedure and call it via exec.


Example:

Runner script, runner.tcl:

set arguments [lassign $argv packageInfo commandName]
package require {*}$packageInfo
puts [$commandName {*}$arguments]
exit

Use script:

# This just makes using the subprocess a little neater
proc runInPackage {packageInfo args} {
    return [exec [info nameofexecutable] runner.tcl $packageInfo {*}$args]
}

# This will call FooBarProc from version 1.2 of the FooBarPackage
set result [runInPackage {FooBarPackage 1.2} FooBarProc 1 2 3 4 5]

There are ways to do more complicated things through suitable marshalling tricks… but this is enough to get you a long long way! Provided your arguments aren't too large.

Upvotes: 0

Related Questions