gh-150836: Mount embedded Tk ZIP in _tkinter on Windows#151562
gh-150836: Mount embedded Tk ZIP in _tkinter on Windows#151562jjhelmus wants to merge 3 commits into
Conversation
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.
| wchar_t tk_path[MAX_PATH]; | ||
| DWORD path_len = GetModuleFileNameW(tk_module, tk_path, MAX_PATH); | ||
|
|
||
| if (path_len == 0 || path_len >= MAX_PATH) { |
There was a problem hiding this comment.
We can't assume MAX_PATH, unfortunately, since it's quite likely that Python could be running in a long path. At a minimum, use 512 instead (which is what is used in dynload_win.c for importing native modules), or we have to do a loop that increases (doubles) the buffer size until path_len < buffer_len.
There was a problem hiding this comment.
If it can be done with Tcl's APIs, go for it.
There was a problem hiding this comment.
I adjust the logic here to loop until a long enough buffer is found using the pattern in Modules/getpath.c:winmodule_to_dict
| Tcl_DStringInit(&utf8_path); | ||
| Tcl_WCharToUtfDString(tk_path, path_len, &utf8_path); | ||
| (void) TclZipfs_Mount(NULL, Tcl_DStringValue(&utf8_path), | ||
| "//zipfs:/lib/tk", NULL); |
There was a problem hiding this comment.
I assume this handles re-mounting without an issue? It seems like it could be called multiple times by someone's code.
There was a problem hiding this comment.
Calling TclZipfs_Mount on an existing mount leaves the original untouched but does raise an error. Since this call passes a null interpreter this error is discarded. Trying to mount a DLL without an embedded Zip also results in a discarded error.
I added a comment about the failures here being harmless.
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.