Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

::tcl_library needed to be set for each interpreter???

1 view
Skip to first unread message

imp...@yahoo.com

unread,
May 14, 2008, 1:53:22 PM5/14/08
to
Hi,

Why there needs to be a tclpreinitscript and a ::tcl_library variable
set before calling Tcl_Init() for that interpreter?
If I set the tclpreinitscript, then on doing a eval on this, it fails
on ::tcl_library path not defined.

The problem I am having is, when I open a new console or tab through
tkcon, it calls the "interp create <somename>", which creates a new
interpreter inside "static Tcl_Interp *SlaveCreate()" funciton in the
file tclInterp.c( in tcl8.5). And, then it gives the error message
that there is no ::tcl_library path defined for that interpreter on
trying to call Tcl_Init(<slaveinterpreter>)!!

What am I missing here?

Thanks,
Mona.

Donald G Porter

unread,
May 14, 2008, 2:10:22 PM5/14/08
to
imp...@yahoo.com wrote:
> Why there needs to be a tclpreinitscript and a ::tcl_library variable
> set before calling Tcl_Init() for that interpreter?

Your question needs more context, because in tclsh the problem you
allege doesn't appear to exist:

% info patch
8.4.19
% interp create slave
slave
% slave eval info exists tcl_library
1

--
| Don Porter Mathematical and Computational Sciences Division |
| donald...@nist.gov Information Technology Laboratory |
| http://math.nist.gov/~DPorter/ NIST |
|______________________________________________________________________|

imp...@yahoo.com

unread,
May 14, 2008, 5:07:29 PM5/14/08
to
> > impm...@yahoo.com wrote:
> > Why there needs to be a tclpreinitscript and a ::tcl_library variable
> > set before calling Tcl_Init() for that interpreter?
>
> donald...@nist.gov wrote:
> % info patch
> 8.4.19
> % interp create slave
> slave
> % slave eval info exists tcl_library
> 1

If I copy the tclsh and the tcl/tk dll to a different folder, then do
the same the commands in tclsh, it gives the error that init.tcl was
not found. This error comes up because their is no tclpreinitscript
set for the interpreter. If we (somehow ) set one, then we would get
the ::tcl_library variable error.
I am able to see this error, as my application is in a different
location than where the tcl library is.
How can I resolve this, so that I don't get any errors?

Thanks,
IRa.


Ron Fox

unread,
May 15, 2008, 7:29:24 AM5/15/08
to
What problem are you trying to solve by copying tclsh and friends
to a different folder? I have a hunch there may be simpler ways to do
what you're trying to do that will side-step this issue.

RF

imp...@yahoo.com

unread,
May 15, 2008, 8:15:46 AM5/15/08
to
On May 15, 7:29 am, Ron Fox <f...@nscl.msu.edu> wrote:
> What problem are you trying to solve by copying tclsh and friends
> to a different folder? I have a hunch there may be simpler ways to do
> what you're trying to do that will side-step this issue.

My application exe is in a different folder (C:/MyApp/bin/win32/
myapp.exe) than where the tcl and it's other packages are residing(C:/
MyApp/tcl/tcl8.5.2/win32..). To run my appln, I have been only
copying the tcl and tk dlls into the same folder location as my appln
exe. I don't copy any tcl or wish or other folders like tcl8.5, tk8.5
etc in that folder. ( The example I gave before about copying tclsh
etc was to tell how one can get the same error I am getting).

Now, when I run the interp create command, then it complains that it
is not finding a valid init.tcl under the folder from where the
application is run from and it's parent folders. And this is how the
code is written under Tcl_Init() funciton in it's tclInit() eval
block. It doesn't make sense to me why it check's these folder
paths. So, to resolve this error I call the tclPreInitSript()( which
looks like, is independent of the interpreter) to set tclPreInitScript
var's value. But, then I get the error from tkcon.tcl file that there
is no ::tcl_library variable set on calling the "interp create..."
from tkcon.tcl( ::tcl_library seems to be interpreter dependent!!!)

I am just learning to use the tcl file functionings, so probably I
might be missing something.
Do you how can I resolve this error? One way would be to copy all the
tcl binaries created( under C:/MyApp/tcl/tcl8.5.2/win32) to where my
app exe is. But , I would like know if there is a simpler approach,
like setting something etc. to resolve the error.

Thanks.

Donald G Porter

unread,
May 15, 2008, 11:18:54 AM5/15/08
to
imp...@yahoo.com wrote:
> If I copy the tclsh and the tcl/tk dll to a different folder,...

...then you break those dlls. Don't Do That.

On Windows, tcl.dll expects to have Tcl's entire matching script
library (init.tcl + several other files) installed in the location
../lib/tclM.m relative to where tcl.dll is. When you move only
the dlls and not these other supporting files, you break Tcl.

You and your users (if any) can work around this breakage by setting
the environment variable TCL_LIBRARY to the directory where init.tcl
and friends are. That's a last resort solution, though. You are
better off not breaking your Tcl install in the first place.

The other solution is to adopt any of the many deployment solutions
that turns multiple file programs making use of Tcl into single
(or double) file programs making use of Tcl. Starkits, starpacks,
freewrap, etc. ActiveState sells tools meant to make this easy,
and several no cost solutions are about as well.

Koen Danckaert

unread,
May 16, 2008, 11:41:12 AM5/16/08
to
Donald G Porter wrote:
> imp...@yahoo.com wrote:
>> If I copy the tclsh and the tcl/tk dll to a different folder,...
>
> ...then you break those dlls. Don't Do That.
>
> On Windows, tcl.dll expects to have Tcl's entire matching script
> library (init.tcl + several other files) installed in the location
> ../lib/tclM.m relative to where tcl.dll is. When you move only
> the dlls and not these other supporting files, you break Tcl.

Well, we have always distributed our applications this way, and never encountered problems. However we don't create slave interps, which is where the problem indeed shows up. Is there a reason to do the search for init.tcl in each interp? I think it would be better to cache it in an interp-independent place.

The way in which we start our applications is by first setting tcl_library from the main C program, then calling Tcl_init():

Tcl_FindExecutable(argv[0]);
Tcl_Interp* ip = Tcl_CreateInterp();
String tcl_lib = ...; /* application-specific */
Tcl_SetVar(ip, "tcl_library", tcl_lib, TCL_GLOBAL_ONLY);
if (Tcl_Init(ip) == TCL_ERROR) error(Tcl_GetStringResult(ip));

This is supported by the following code comment in tclInterp.c, line 307:
/*
* In order to find init.tcl during initialization, the following script
* is invoked by Tcl_Init(). It looks in several different directories:
*
* $tcl_library - can specify a primary location, if set, no
* other locations will be checked. This is the
* recommended way for a program that embeds
* Tcl to specifically tell Tcl where to find
* an init.tcl file.


However, the workaround (for when multiple interps are needed) is easy: simply add the following line to the main C program:

Tcl_SetVar2(ip, "env", "TCL_LIBRARY", tcl_lib, TCL_GLOBAL_ONLY);

--Koen

Donald G Porter

unread,
May 20, 2008, 4:33:16 PM5/20/08
to
Koen Danckaert wrote:
> The way in which we start our applications is by first setting
> tcl_library from the main C program, then calling Tcl_init():
>
> Tcl_FindExecutable(argv[0]);
> Tcl_Interp* ip = Tcl_CreateInterp();
> String tcl_lib = ...; /* application-specific */
> Tcl_SetVar(ip, "tcl_library", tcl_lib, TCL_GLOBAL_ONLY);
> if (Tcl_Init(ip) == TCL_ERROR) error(Tcl_GetStringResult(ip));

For the most part that seems fine. You are using the supported
mechanism for your program to assert that it knows where the
Tcl script library is.

The tricky bit, of course, is just how it is that your program
knows this. And how robust that knowledge or discovery is if
your program gets moved into an environment that is not precisely
the same as the environment in which it was originally developed.

> However, the workaround (for when multiple interps are needed) is easy:
> simply add the following line to the main C program:
>
> Tcl_SetVar2(ip, "env", "TCL_LIBRARY", tcl_lib, TCL_GLOBAL_ONLY);

Yes, that's effective. I use that myself. Once the master interp has
solved the "find init.tcl" problem, that's a handy way to give all
slaves the same answer straight away.

0 new messages