mirror of
https://github.com/python/cpython.git
synced 2026-06-27 19:36:07 +00:00
[3.15] gh-150836: Mount embedded Tk ZIP in _tkinter on Windows (GH-151735)
Tcl/Tk 9 may embed the Tk script library in the Tk DLL on Windows. This embedded library is not found by Tcl by default.
Mount the loaded Tk DLL as a zipfs archive before calling Tk_Init(), so Tk can find its embedded tk_library using its existing library discovery logic.
Preserve Tk_Init()'s normal path if the library is not embedded.
(cherry picked from commit c4eb3adbb4)
Co-authored-by: Jonathan J. Helmus <jjhelmus@gmail.com>
This commit is contained in:
parent
a30acf2495
commit
b83a217558
4 changed files with 61 additions and 3 deletions
|
|
@ -0,0 +1 @@
|
|||
Make installed tkinter work with Tcl/Tk 9 builds that embed the Tk script library in the Tk DLL on Windows.
|
||||
|
|
@ -53,6 +53,10 @@ Copyright (C) 1994 Steen Lumholt.
|
|||
# include <tk.h>
|
||||
#endif
|
||||
|
||||
#if defined(MS_WINDOWS) && TK_MAJOR_VERSION >= 9
|
||||
# include <tkPlatDecls.h>
|
||||
#endif
|
||||
|
||||
#include "tkinter.h"
|
||||
|
||||
#if TK_HEX_VERSION < 0x0805020c
|
||||
|
|
@ -175,6 +179,57 @@ _get_tcl_lib_path(void)
|
|||
}
|
||||
#endif /* MS_WINDOWS */
|
||||
|
||||
#if defined(MS_WINDOWS) && TK_MAJOR_VERSION >= 9
|
||||
static void
|
||||
mount_tk_dll_zip(void)
|
||||
{
|
||||
HINSTANCE tk_module = Tk_GetHINSTANCE();
|
||||
wchar_t *tk_path = NULL;
|
||||
DWORD path_len = 0;
|
||||
for (DWORD buffer_len = 256;
|
||||
tk_path == NULL && buffer_len < (1024 * 1024);
|
||||
buffer_len *= 2)
|
||||
{
|
||||
tk_path = (wchar_t *)PyMem_RawMalloc(
|
||||
buffer_len * sizeof(*tk_path));
|
||||
if (tk_path != NULL) {
|
||||
path_len = GetModuleFileNameW(tk_module, tk_path, buffer_len);
|
||||
if (path_len == buffer_len) {
|
||||
PyMem_RawFree(tk_path);
|
||||
tk_path = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (tk_path == NULL || path_len == 0) {
|
||||
PyMem_RawFree(tk_path);
|
||||
return;
|
||||
}
|
||||
|
||||
Tcl_DString utf8_path;
|
||||
|
||||
Tcl_DStringInit(&utf8_path);
|
||||
Tcl_WCharToUtfDString(tk_path, path_len, &utf8_path);
|
||||
/* Failure is harmless if the DLL has no embedded ZIP or if another
|
||||
interpreter has already mounted it. */
|
||||
(void) TclZipfs_Mount(NULL, Tcl_DStringValue(&utf8_path),
|
||||
"//zipfs:/lib/tk", NULL);
|
||||
Tcl_DStringFree(&utf8_path);
|
||||
PyMem_RawFree(tk_path);
|
||||
}
|
||||
#endif
|
||||
|
||||
int
|
||||
Tkinter_TkInit(Tcl_Interp *interp)
|
||||
{
|
||||
#if defined(MS_WINDOWS) && TK_MAJOR_VERSION >= 9
|
||||
/* Tcl/Tk 9 may embed the tk_library in the Tk DLL which tcl_findLibrary
|
||||
does not search. Mount the DLL using Zipfs if possible. */
|
||||
mount_tk_dll_zip();
|
||||
#endif
|
||||
return Tk_Init(interp);
|
||||
}
|
||||
|
||||
/* The threading situation is complicated. Tcl is not thread-safe, except
|
||||
when configured with --enable-threads.
|
||||
|
||||
|
|
@ -544,7 +599,7 @@ Tcl_AppInit(Tcl_Interp *interp)
|
|||
return TCL_OK;
|
||||
}
|
||||
|
||||
if (Tk_Init(interp) == TCL_ERROR) {
|
||||
if (Tkinter_TkInit(interp) == TCL_ERROR) {
|
||||
PySys_WriteStderr("Tk_Init error: %s\n", Tcl_GetStringResult(interp));
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
|
@ -2988,7 +3043,7 @@ _tkinter_tkapp_loadtk_impl(TkappObject *self)
|
|||
return NULL;
|
||||
}
|
||||
if (_tk_exists == NULL || strcmp(_tk_exists, "1") != 0) {
|
||||
if (Tk_Init(interp) == TCL_ERROR) {
|
||||
if (Tkinter_TkInit(interp) == TCL_ERROR) {
|
||||
Tkinter_Error(self);
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ Tcl_AppInit(Tcl_Interp *interp)
|
|||
return TCL_OK;
|
||||
}
|
||||
|
||||
if (Tk_Init(interp) == TCL_ERROR) {
|
||||
if (Tkinter_TkInit(interp) == TCL_ERROR) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -16,4 +16,6 @@
|
|||
(TK_RELEASE_LEVEL << 8) | \
|
||||
(TK_RELEASE_SERIAL << 0))
|
||||
|
||||
int Tkinter_TkInit(Tcl_Interp *interp);
|
||||
|
||||
#endif /* !TKINTER_H */
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue