@@ -273,77 +273,94 @@ static PyMethodDef functions[] = {
273273#define TKINTER_PKG " tkinter"
274274#define TKINTER_MOD " _tkinter"
275275// From module __file__ attribute to char *string for dlopen.
276- #define FNAME2CHAR (s ) (PyBytes_AsString(PyUnicode_EncodeFSDefault(s)))
276+ char *fname2char (PyObject *fname)
277+ {
278+ PyObject *bytes = PyUnicode_EncodeFSDefault (fname);
279+ if (bytes == NULL ) {
280+ return NULL ;
281+ }
282+ return PyBytes_AsString (bytes);
283+ }
277284#else
278285#define TKINTER_PKG " Tkinter"
279286#define TKINTER_MOD " tkinter"
280287// From module __file__ attribute to char *string for dlopen
281- #define FNAME2CHAR (s ) (PyString_AsString(s))
288+ #define fname2char (s ) (PyString_AsString(s))
282289#endif
283290
284291void *_dfunc (void *lib_handle, const char *func_name)
285292{
286- // Load function, unless there has been a previous error. If so, then
287- // return NULL. If there is an error loading the function, return NULL
288- // and set error flag.
289- static int have_error = 0 ;
290- void *func = NULL ;
291- if (have_error == 0 ) {
292- // reset errors
293- dlerror ();
294- func = dlsym (lib_handle, func_name);
293+ // Load function `func_name` from `lib_handle`.
294+ // Set Python exception if we can't find `func_name` in `lib_handle`.
295+ // Returns function pointer or NULL if not present.
296+
297+ // Reset errors.
298+ dlerror ();
299+ void *func = dlsym (lib_handle, func_name);
300+ if (func == NULL ) {
295301 const char *error = dlerror ();
296- if (error != NULL ) {
297- PyErr_SetString (PyExc_RuntimeError, error);
298- have_error = 1 ;
299- }
302+ PyErr_SetString (PyExc_RuntimeError, error);
300303 }
301304 return func;
302305}
303306
304- int _func_loader (void *tkinter_lib )
307+ int _func_loader (void *lib )
305308{
306309 // Fill global function pointers from dynamic lib.
307- // Return 0 fur success; 1 otherwise.
308- TCL_CREATE_COMMAND = (tcl_cc) _dfunc (tkinter_lib, " Tcl_CreateCommand" );
309- TCL_APPEND_RESULT = (tcl_app_res) _dfunc (tkinter_lib, " Tcl_AppendResult" );
310- TK_MAIN_WINDOW = (tk_mw) _dfunc (tkinter_lib, " Tk_MainWindow" );
311- TK_FIND_PHOTO = (tk_fp) _dfunc (tkinter_lib, " Tk_FindPhoto" );
312- TK_PHOTO_PUTBLOCK = (tk_ppb_nc) _dfunc (tkinter_lib, " Tk_PhotoPutBlock_NoComposite" );
313- TK_PHOTO_BLANK = (tk_pb) _dfunc (tkinter_lib, " Tk_PhotoBlank" );
314- return (TK_PHOTO_BLANK == NULL );
310+ // Return 1 if any pointer is NULL, 0 otherwise.
311+ return (
312+ ((TCL_CREATE_COMMAND = (tcl_cc)
313+ _dfunc (lib, " Tcl_CreateCommand" )) == NULL ) ||
314+ ((TCL_APPEND_RESULT = (tcl_app_res)
315+ _dfunc (lib, " Tcl_AppendResult" )) == NULL ) ||
316+ ((TK_MAIN_WINDOW = (tk_mw)
317+ _dfunc (lib, " Tk_MainWindow" )) == NULL ) ||
318+ ((TK_FIND_PHOTO = (tk_fp)
319+ _dfunc (lib, " Tk_FindPhoto" )) == NULL ) ||
320+ ((TK_PHOTO_PUTBLOCK = (tk_ppb_nc)
321+ _dfunc (lib, " Tk_PhotoPutBlock_NoComposite" )) == NULL ) ||
322+ ((TK_PHOTO_BLANK = (tk_pb)
323+ _dfunc (lib, " Tk_PhotoBlank" )) == NULL ));
315324}
316325
317326int load_tkinter_funcs (void )
318327{
319328 // Load tkinter global funcs from tkinter compiled module.
320329 // Return 0 for success, non-zero for failure.
321330 int ret = -1 ;
322- PyObject *pModule, *pSubmodule, *pString;
331+ void *tkinter_lib;
332+ char *tkinter_libname;
333+ PyObject *pModule = NULL , *pSubmodule = NULL , *pString = NULL ;
323334
324335 pModule = PyImport_ImportModule (TKINTER_PKG);
325- if (pModule != NULL ) {
326- pSubmodule = PyObject_GetAttrString (pModule, TKINTER_MOD);
327- if (pSubmodule != NULL ) {
328- pString = PyObject_GetAttrString (pSubmodule, " __file__" );
329- if (pString != NULL ) {
330- char *tkinter_libname = FNAME2CHAR (pString);
331- void *tkinter_lib = dlopen (tkinter_libname, RTLD_LAZY);
332- if (tkinter_lib == NULL ) {
333- PyErr_SetString (PyExc_RuntimeError,
334- " Cannot dlopen tkinter module file" );
335- } else {
336- ret = _func_loader (tkinter_lib);
337- // dlclose probably safe because tkinter has been
338- // imported.
339- dlclose (tkinter_lib);
340- }
341- Py_DECREF (pString);
342- }
343- Py_DECREF (pSubmodule);
344- }
345- Py_DECREF (pModule);
336+ if (pModule == NULL ) {
337+ goto exit;
338+ }
339+ pSubmodule = PyObject_GetAttrString (pModule, TKINTER_MOD);
340+ if (pSubmodule == NULL ) {
341+ goto exit;
342+ }
343+ pString = PyObject_GetAttrString (pSubmodule, " __file__" );
344+ if (pString == NULL ) {
345+ goto exit;
346+ }
347+ tkinter_libname = fname2char (pString);
348+ if (tkinter_libname == NULL ) {
349+ goto exit;
350+ }
351+ tkinter_lib = dlopen (tkinter_libname, RTLD_LAZY);
352+ if (tkinter_lib == NULL ) {
353+ PyErr_SetString (PyExc_RuntimeError,
354+ " Cannot dlopen tkinter module file" );
355+ goto exit;
346356 }
357+ ret = _func_loader (tkinter_lib);
358+ // dlclose probably safe because tkinter has been imported.
359+ dlclose (tkinter_lib);
360+ exit:
361+ Py_XDECREF (pModule);
362+ Py_XDECREF (pSubmodule);
363+ Py_XDECREF (pString);
347364 return ret;
348365}
349366#endif
0 commit comments