Python 3.4.1 installer on Mac links Python to old Tcl/Tk
Christian Gollwitzer
auriocus at gmx.de
Sun Oct 5 15:26:35 EDT 2014
Am 04.10.14 07:53, schrieb Ned Deily:
> In article <m0n3n3$48j$1 at dont-email.me>,
> Kevin Walzer <kw at codebykevin.com> wrote:
>> A Tcl library compiled for 8.5 can be loaded into 8.6 with no
>> re-compiling required because of stubs.
>
> It has nothing to do with Python per se; that's just the way linking
> with OS frameworks work.
> [...]
>
> When Python or other programs link with a framework, they use the cc or
> ld -framework option, rather than -l:
> -framework Tcl -framework Tk
>
> That causes the linker to look in the default search paths for
> frameworks, /Library/Frameworks followed by /System/Library/Frameworks.
> The install names of the framework shared libraries used are embedded in
> the Mach-O file (executable, bundle, or shared library) produced by ld.
> So the stub library archive is there but is not used, AFAIK.
Then it is done in a non-optimal way, though admittedly in the case of
Tkinter, which is a hybrid Python/Tcl extension, the optimal way is not
obvious. In the Tcl world, there are two different ways to link to Tcl
(and analogously to Tk):
A) you can link directly to libtcl.dylib (.so, .dll)
B) you can define USE_TCL_STUBS during compilation and link to
libtclstub.a
If you embed an interpreter, you must do A. So for Tkinter, linking
directly to the dynamic lib (== -framework in OSX) is correct.
If you extend an interpreter by defining new commands, new Tcl_Obj, new
Tk image types etc., you can do either A or B, but the recommended way
is always B because this makes it possible to load an extension into any
later interpreter than the one it was compiled against. The magic behind
stubs are macros which replace function calls by invocations of an index
into a function pointer table; that table is initialized at runtime,
when the extension calls Tcl_InitStubs().
Now, tkagg is not loaded by the Tcl load() command. This means that
after loading via Pythons import, the stub table should be initialized.
Obviously this is not the case; if I'm not mistaken, just before this line
https://github.com/matplotlib/matplotlib/blob/master/src/_tkagg.cpp#L252
if you insert
Tcl_InitStubs(interp, TCL_VERSION, 0);
Tk_InitStubs(interp, TCL_VERSION, 0);
then it should be possible to compile tkagg with -DUSE_TCL_STUBS
-DUSE_TK_STUBS, link to tclstub and tkstub and load the resulting tkagg
into any Tkinter that links to an interpreter at least as new as
TCL_VERSION. (If the result of either call is NULL, the interpreter is
too old). Admittedly I'm too lazy to setup a build environment for
matplotlib to try if this actually works.
>
> There may be other ways to do it but that's how Python has always linked
> to Tcl and Tk. FWIW, that's how both Apple's and ActiveState's wish
> executables are linked as well:
wish is a type A program, it creates an interpreter and therefore must
link to the actual library. So is Tkinter. But Tkagg is not, it extends
a preexisting interpreter.
Christian
More information about the Python-list
mailing list