Go down


Post  ^4GT^ on Tue Dec 09, 2008 7:11 am

Last update on October 20th 2008 for version 1.0

0. FAQ
> What is "supported mode"?

> Invoking the interpreter
> Notes on $dllcall and asynchronous calls
> Embedding Tcl into scripts
> Caching embedded code

> mirc package
> mirc function
> Passing variables from mIRC




0. FAQ

> What is "supported mode"?

Tcl4mIRC relies on the CLB (Common Language Bridge) which is part
of the Dynamic Languages 4 mIRC project. The CLB extends the way
a DLL can communicate with mIRC, enabling it specifically to be
able to access event specific identifiers, like $opnick in the
ON OP event. In addition to extended functionality, this mode is
roughly 3 times faster than using the standard SendMessage API
documented in the mIRC help (/help SendMessage).

However, a drawback of this mode is that it requires specific
knowledge about the makeup of the mIRC binary that is being run.
In other words, to make use of the CLB's extended functionality,
the version of mIRC used with the DLL must be explicitly supported
by the CLB, hence "supported mode".

CLB is able to fallback on the standard SendMessage API when the
version of mIRC is not supported, but beware that you may be using
a script that requires the extended functionality that the CLB
provides. If you are using Tcl4mIRC in unsupported mode, verify
that you do not have any embedded scripts inside events that make
use of event specific identifiers. In such a case, your events will
not function properly.


> Invoking the interpreter

The first way to run Tcl code is to simply invoke the evaluation
method by simply calling:


* Note that /tcl is a convenience alias specified in tcl.mrc

You can also use $tcl(CODE_HERE) to retrieve the return value
from a block of Tcl code.

> Notes on $dllcall and asynchronous calls

Short answer: don't use it.

Long answer:

Tcl has an event driven interpreter model. Threading is implicit,
not explicit. Therefore, making asynchronous calls in Tcl is
much like making asynchronous calls in mIRC: you use a timer
which will inevitably be processed by the Tcl event loop. This
means that you cannot and should not use `$dllcall` to perform
asynchronous calls, because Tcl does not work properly across
threads. Doing so will likely crash mIRC.

> Embedding Tcl into scripts

Most people don't just want Tcl sitting on the sidelines while
mIRC does its thing. For this reason, you have the ability to
embed your Ruby code directly into your mIRC scripts seamlessly.

To do this, you must "memorize" the following snippet of code
to have Tcl4mIRC jump from mIRC code into your Tcl script:

if $($has_tcl,2) {
# Tcl code goes here

If you're curious to know what it does, I can explain. $has_tcl
will return a call to the DLL to invoke the interpreter and parse
the code starting at the beginning of the if extending to the end.
The command must be $() evaluated to get $scriptline so that it knows
where to begin parsing from. The identifier then returns $false so
that mIRC ignores the if-block, happily skipping over the otherwise-
invalid script.

> Caching embedded code

To speed up the execution of each embedded call, you can cache your
code in memory to avoid recompiling the Tcl code each round. To do
this, simply use $has_cached_tcl (or $has_cached_async_tcl) instead.

IMPORTANT: Note that the Tcl caching model is such that once you cache
a block of code it can not be overidden by calling the non-
cached function anymore. To clear the cache you will have
to unload the DLL completely with `/tcl_unload`.

Caching is not "on" by default because most people will most likely
have to make changes to their code before finalizing it, and having
Tcl4mIRC cache all the time would cause a lot of headaches in
debugging. For this reason, the recommended flow of coding is to use
$has_tcl until you are positive that you have a working product,
and only then change the starting line to $has_cached_tcl. It may
also be beneficial to add a note to yourself that you are caching
the script results.


> mirc package

Tcl4mIRC registers a package called 'mirc' for to get information
about the DLL version, etc. It can be accessed via the standard Tcl
package info command:

/tcl puts [package present mirc]

> mirc function

The `mirc` function is the main command to use to have Tcl communicate
with mIRC. The function takes a command, variable, or identifier as
an argument and evaluates the expression, returning a result (if it
is not a command). For example:

mirc "echo -a hello world"

Notice that the '/' prefix is not necessary, though it is allowed.

* Note: The mirc command will decide whether to evaluate code as an
identifier or variable depending on the first character in
the command string. If the first character is '%' or '$',
the string will be evaluated, otherwise it will be executed.
This means that the command "%x = 2" will not attempt to set
the variable %x to 2. Please use "set %x 2" to do that
instead. Subsequent versions of Tcl4mIRC will address this
issue, perhaps by splitting evaluation and commands into
two separate functions.

To evaluate an identifier use (in Tcl we always escape '$' when we
are not accessing a Tcl variable):

puts [mirc \$calc(1 + 2)]


puts [mirc %a_variable]

* Note: Remember to escape '$' and '%' characters if you call the
above code using /tcl or $tcl since you will be subject to
parsing by mIRC before your data reaches Tcl4mIRC. In embedded
code there is no need to escape anything for mIRC's sake.

If you run Tcl in "supported mode" (See "supported mode" in the FAQ
for details) then you can take advantage of this command to evaluate
event specific identifiers, for example, $opnick in an ON OP event.

> Passing variables from mIRC

It is likely that you will need to pass data to and from Tcl when
creating a script. While the CLB does support event specific
identifiers to reduce the number of data needed to be manually
passed in and out of mIRC, the CLB does not support local variables
or the $1- identifier family, and therefore cannot communicate
completely transparently with mIRC.

To solve this problem, you must unfortunately set the variables
that Tcl4mIRC needs to read globally, unsetting them at the end
of your alias or event. /set -u0 will not work to avoid the unset
command at the end. A way to access local variables via the CLB
is being worked on. An example of communicating between mIRC
and Tcl would be:

alias tcl_strlen {
set %data $1-
tcl puts [string length [mirc {%data}]]
unset %data

/tcl_strlen Hello world


Tcl4mIRC sends a few signals to mIRC now and then that can be caught
by the scripter. For more information on the SIGNAL event, read mIRC's
help under "ON SIGNAL". The following signals are supplied:


This signal will be triggered in the rare case where the CLB
cannot communicate with mIRC. This is a critical error and
should be handled by halting further script processing. Error
details will be filled into $1-.


Triggered when TCL is finished loading into memory. You can
use this to load any important TCL support libraries. The
identifier $1 will be filled with the "supported mode" value
as $true / $false (whether or not the CLB is running in
supported mode). See "supported mode" in the FAQ for more
information on this value.


Triggered when Tcl is about to read a block of text either
from standard output or standard error. You can use this
to /linesep if you wish.


Triggered when Tcl reads *one line* of data from standard
output or standard error. $1- is filled with the line contents.


Triggered when Tcl finishes printing a block of text from
standard output or standard error.


Ideally, Tk should be run within a separate process from mIRC. This will
enable your Tk application to perform proper shutdown procedures. You can
do this by using `exec` to run `wish` on your Tcl script (exec wish myfile.tcl)
However, if you must run Tk code within the same process as mIRC, there are a
few things to keep in mind:

1. As hinted above, Tcl/Tk is running in the same process space as mIRC.
This means that if your Tk application calls `exit` to shutdown, it will
close mIRC as well.

2. Closing the root level window (the one that pops up when you require Tk)
will disable the Tk interpreter completely. You will probably see the
following error message if you do so and try to use Tk:

can't invoke "tk" command: application has been destroyed

You can reinvoke Tk by unloading the dll (/dll -u $tcl_dll) and reloading
it. Instead of closing the root window, hide it with:

/tcl wm withdraw .

You can reshow any withdrawn windows with `wm deiconify path`:

/tcl wm deiconify .

To ensure that you do not accidentally click the X button, you can add the
following to any Tk initialization commands you may be doing:

alias tk_init {
tcl package require Tk
tcl wm protocol . WM_DELETE_WINDOW {wm withdraw .}

Again, the above issues can be ignored if you run your Tk applications in their
own process space. -bersambung

Number of posts : 281
Age : 35
Location : Kluang,JOHOR
Registration date : 2008-06-08

View user profile

Back to top Go down

Back to top

- Similar topics

Permissions in this forum:
You cannot reply to topics in this forum