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