Am 04.10.14 07:53, schrieb Ned Deily:
In article <m0n3n3$48j$1...@dont-email.me>,
  Kevin Walzer <k...@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


--
https://mail.python.org/mailman/listinfo/python-list

Reply via email to