Skip to content

Commit 677a3b2

Browse files
authored
Merge pull request #10936 from anntzer/tkc
MNT: Simplify tkagg C extension.
2 parents aa7c8b4 + 314420a commit 677a3b2

File tree

1 file changed

+38
-78
lines changed

1 file changed

+38
-78
lines changed

src/_tkagg.cpp

+38-78
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ static int PyAggImagePhoto(ClientData clientdata, Tcl_Interp *interp, int
7575
}
7676
/* get buffer from str which is "height width ptr" */
7777
if (sscanf(argv[2], IMG_FORMAT, &hdata, &wdata, &pdata) != 3) {
78-
TCL_APPEND_RESULT(interp,
78+
TCL_APPEND_RESULT(interp,
7979
"error reading data, expected height width ptr",
8080
(char *)NULL);
8181
return TCL_ERROR;
@@ -291,8 +291,7 @@ int get_tcl(HMODULE hMod)
291291
if (TCL_CREATE_COMMAND == NULL) { // Maybe not TCL module
292292
return 0;
293293
}
294-
TCL_APPEND_RESULT = (Tcl_AppendResult_t) _dfunc(hMod,
295-
"Tcl_AppendResult");
294+
TCL_APPEND_RESULT = (Tcl_AppendResult_t) _dfunc(hMod, "Tcl_AppendResult");
296295
return (TCL_APPEND_RESULT == NULL) ? -1 : 1;
297296
}
298297

@@ -306,20 +305,20 @@ int get_tk(HMODULE hMod)
306305
if (TK_MAIN_WINDOW == NULL) { // Maybe not Tk module
307306
return 0;
308307
}
309-
return ( // -1 if any remaining symbols are NULL
308+
return // -1 if any remaining symbols are NULL
310309
((TK_FIND_PHOTO = (Tk_FindPhoto_t)
311310
_dfunc(hMod, "Tk_FindPhoto")) == NULL) ||
312311
((TK_PHOTO_PUT_BLOCK_NO_COMPOSITE = (Tk_PhotoPutBlock_NoComposite_t)
313312
_dfunc(hMod, "Tk_PhotoPutBlock_NoComposite")) == NULL) ||
314313
((TK_PHOTO_BLANK = (Tk_PhotoBlank_t)
315-
_dfunc(hMod, "Tk_PhotoBlank")) == NULL))
314+
_dfunc(hMod, "Tk_PhotoBlank")) == NULL)
316315
? -1 : 1;
317316
}
318317

319-
int load_tkinter_funcs(void)
318+
void load_tkinter_funcs(void)
320319
{
321320
// Load TCL and Tk functions by searching all modules in current process.
322-
// Return 0 for success, non-zero for failure.
321+
// Sets an error on failure.
323322

324323
HMODULE hMods[1024];
325324
HANDLE hProcess;
@@ -337,17 +336,17 @@ int load_tkinter_funcs(void)
337336
if (!found_tcl) {
338337
found_tcl = get_tcl(hMods[i]);
339338
if (found_tcl == -1) {
340-
return 1;
339+
return;
341340
}
342341
}
343342
if (!found_tk) {
344343
found_tk = get_tk(hMods[i]);
345344
if (found_tk == -1) {
346-
return 1;
345+
return;
347346
}
348347
}
349348
if (found_tcl && found_tk) {
350-
return 0;
349+
return;
351350
}
352351
}
353352
}
@@ -357,7 +356,7 @@ int load_tkinter_funcs(void)
357356
} else {
358357
PyErr_SetString(PyExc_RuntimeError, "Could not find Tk routines");
359358
}
360-
return 1;
359+
return;
361360
}
362361

363362
#else // not Windows
@@ -367,16 +366,6 @@ int load_tkinter_funcs(void)
367366
* tkinter uses these symbols, and the symbols are therefore visible in the
368367
* tkinter dynamic library (module).
369368
*/
370-
// From module __file__ attribute to char *string for dlopen.
371-
char *fname2char(PyObject *fname)
372-
{
373-
PyObject* bytes;
374-
bytes = PyUnicode_EncodeFSDefault(fname);
375-
if (bytes == NULL) {
376-
return NULL;
377-
}
378-
return PyBytes_AsString(bytes);
379-
}
380369

381370
#include <dlfcn.h>
382371

@@ -391,8 +380,7 @@ void *_dfunc(void *lib_handle, const char *func_name)
391380
dlerror();
392381
func = dlsym(lib_handle, func_name);
393382
if (func == NULL) {
394-
const char *error = dlerror();
395-
PyErr_SetString(PyExc_RuntimeError, error);
383+
PyErr_SetString(PyExc_RuntimeError, dlerror());
396384
}
397385
return func;
398386
}
@@ -401,7 +389,7 @@ int _func_loader(void *lib)
401389
{
402390
// Fill global function pointers from dynamic lib.
403391
// Return 1 if any pointer is NULL, 0 otherwise.
404-
return (
392+
return
405393
((TCL_CREATE_COMMAND = (Tcl_CreateCommand_t)
406394
_dfunc(lib, "Tcl_CreateCommand")) == NULL) ||
407395
((TCL_APPEND_RESULT = (Tcl_AppendResult_t)
@@ -413,75 +401,50 @@ int _func_loader(void *lib)
413401
((TK_PHOTO_PUT_BLOCK_NO_COMPOSITE = (Tk_PhotoPutBlock_NoComposite_t)
414402
_dfunc(lib, "Tk_PhotoPutBlock_NoComposite")) == NULL) ||
415403
((TK_PHOTO_BLANK = (Tk_PhotoBlank_t)
416-
_dfunc(lib, "Tk_PhotoBlank")) == NULL));
404+
_dfunc(lib, "Tk_PhotoBlank")) == NULL);
417405
}
418406

419-
int load_tkinter_funcs(void)
407+
void load_tkinter_funcs(void)
420408
{
421409
// Load tkinter global funcs from tkinter compiled module.
422-
// Return 0 for success, non-zero for failure.
423-
int ret = -1;
410+
// Sets an error on failure.
424411
void *main_program, *tkinter_lib;
425-
char *tkinter_libname;
426-
PyObject *pModule = NULL, *pSubmodule = NULL, *pString = NULL;
412+
PyObject *module = NULL, *py_path = NULL, *py_path_b = NULL;
413+
char *path;
427414

428-
// Try loading from the main program namespace first
415+
// Try loading from the main program namespace first.
429416
main_program = dlopen(NULL, RTLD_LAZY);
430417
if (_func_loader(main_program) == 0) {
431-
return 0;
418+
goto exit;
432419
}
433420
// Clear exception triggered when we didn't find symbols above.
434421
PyErr_Clear();
435422

436-
// Now try finding the tkinter compiled module
437-
pModule = PyImport_ImportModule("tkinter");
438-
if (pModule == NULL) {
439-
goto exit;
440-
}
441-
pSubmodule = PyObject_GetAttrString(pModule, "_tkinter");
442-
if (pSubmodule == NULL) {
443-
goto exit;
423+
// Handle PyPy first, as that import will correctly fail on CPython.
424+
module = PyImport_ImportModule("_tkinter.tklib_cffi"); // PyPy
425+
if (!module) {
426+
PyErr_Clear();
427+
module = PyImport_ImportModule("_tkinter"); // CPython
444428
}
445-
pString = PyObject_GetAttrString(pSubmodule, "__file__");
446-
if (pString == NULL) {
429+
if (!(module &&
430+
(py_path = PyObject_GetAttrString(module, "__file__")) &&
431+
(py_path_b = PyUnicode_EncodeFSDefault(py_path)) &&
432+
(path = PyBytes_AsString(py_path_b)))) {
447433
goto exit;
448434
}
449-
tkinter_libname = fname2char(pString);
450-
if (tkinter_libname == NULL) {
435+
tkinter_lib = dlopen(path, RTLD_LAZY);
436+
if (!tkinter_lib) {
437+
PyErr_SetString(PyExc_RuntimeError, dlerror());
451438
goto exit;
452439
}
453-
tkinter_lib = dlopen(tkinter_libname, RTLD_LAZY);
454-
if (tkinter_lib == NULL) {
455-
/* Perhaps it is a cffi module, like in PyPy? */
456-
pString = PyObject_GetAttrString(pSubmodule, "tklib_cffi");
457-
if (pString == NULL) {
458-
goto fail;
459-
}
460-
pString = PyObject_GetAttrString(pString, "__file__");
461-
if (pString == NULL) {
462-
goto fail;
463-
}
464-
tkinter_libname = fname2char(pString);
465-
if (tkinter_libname == NULL) {
466-
goto fail;
467-
}
468-
tkinter_lib = dlopen(tkinter_libname, RTLD_LAZY);
469-
}
470-
if (tkinter_lib == NULL) {
471-
goto fail;
472-
}
473-
ret = _func_loader(tkinter_lib);
474-
// dlclose probably safe because tkinter has been imported.
440+
_func_loader(tkinter_lib);
441+
// dlclose is safe because tkinter has been imported.
475442
dlclose(tkinter_lib);
476443
goto exit;
477-
fail:
478-
PyErr_SetString(PyExc_RuntimeError,
479-
"Cannot dlopen tkinter module file");
480444
exit:
481-
Py_XDECREF(pModule);
482-
Py_XDECREF(pSubmodule);
483-
Py_XDECREF(pString);
484-
return ret;
445+
Py_XDECREF(module);
446+
Py_XDECREF(py_path);
447+
Py_XDECREF(py_path_b);
485448
}
486449
#endif // end not Windows
487450

@@ -491,9 +454,6 @@ static PyModuleDef _tkagg_module = {
491454

492455
PyMODINIT_FUNC PyInit__tkagg(void)
493456
{
494-
PyObject *m;
495-
496-
m = PyModule_Create(&_tkagg_module);
497-
498-
return (load_tkinter_funcs() == 0) ? m : NULL;
457+
load_tkinter_funcs();
458+
return PyErr_Occurred() ? NULL : PyModule_Create(&_tkagg_module);
499459
}

0 commit comments

Comments
 (0)