99 */
1010#define PY_SSIZE_T_CLEAN
1111#include < Python.h>
12- #include < cstdlib>
13- #include < cstdio>
14- #include < sstream>
15-
16- #include < agg_basics.h> // agg:int8u
1712
1813#ifdef _WIN32
1914#include < windows.h>
15+ #define PSAPI_VERSION 1
16+ #include < psapi.h> // Must be linked with 'psapi' library
17+ #define dlsym GetProcAddress
18+ #else
19+ #include < dlfcn.h>
2020#endif
2121
2222// Include our own excerpts from the Tcl / Tk headers
2323#include " _tkmini.h"
24-
2524#include " py_converters.h"
2625
27- #if defined(_MSC_VER)
28- # define IMG_FORMAT " %d %d %Iu"
29- #else
30- # define IMG_FORMAT " %d %d %zu"
31- #endif
32- #define BBOX_FORMAT " %f %f %f %f"
33-
34- typedef struct
35- {
36- PyObject_HEAD
37- Tcl_Interp *interp;
38- } TkappObject;
39-
4026// Global vars for Tcl / Tk functions. We load these symbols from the tkinter
4127// extension module or loaded Tcl / Tk libraries at run-time.
42- static Tcl_CreateCommand_t TCL_CREATE_COMMAND;
43- static Tcl_AppendResult_t TCL_APPEND_RESULT;
44- static Tk_MainWindow_t TK_MAIN_WINDOW;
4528static Tk_FindPhoto_t TK_FIND_PHOTO;
4629static Tk_PhotoPutBlock_NoComposite_t TK_PHOTO_PUT_BLOCK_NO_COMPOSITE;
47- static Tk_PhotoBlank_t TK_PHOTO_BLANK;
4830
4931static PyObject *mpl_tk_blit (PyObject *self, PyObject *args)
5032{
@@ -118,7 +100,6 @@ Win32_SetForegroundWindow(PyObject *module, PyObject *args)
118100#endif
119101
120102static PyMethodDef functions[] = {
121- /* Tkinter interface stuff */
122103 { " blit" , (PyCFunction)mpl_tk_blit, METH_VARARGS },
123104#ifdef _WIN32
124105 { " Win32_GetForegroundWindow" , (PyCFunction)Win32_GetForegroundWindow, METH_VARARGS },
@@ -128,6 +109,19 @@ static PyMethodDef functions[] = {
128109};
129110
130111// Functions to fill global TCL / Tk function pointers by dynamic loading
112+
113+ template <class T >
114+ int load_tk (T lib)
115+ {
116+ // Try to fill Tk global vars with function pointers. Return the number of
117+ // functions found.
118+ return
119+ !!(TK_FIND_PHOTO =
120+ (Tk_FindPhoto_t)dlsym (lib, " Tk_FindPhoto" )) +
121+ !!(TK_PHOTO_PUT_BLOCK_NO_COMPOSITE =
122+ (Tk_PhotoPutBlock_NoComposite_t)dlsym (lib, " Tk_PhotoPutBlock_NoComposite" ));
123+ }
124+
131125#ifdef _WIN32
132126
133127/*
@@ -137,102 +131,24 @@ static PyMethodDef functions[] = {
137131 * Python, we scan all modules in the running process for the TCL and Tk
138132 * function names.
139133 */
140- #define PSAPI_VERSION 1
141- #include < psapi.h>
142- // Must be linked with 'psapi' library
143-
144- FARPROC _dfunc (HMODULE lib_handle, const char *func_name)
145- {
146- // Load function `func_name` from `lib_handle`.
147- // Set Python exception if we can't find `func_name` in `lib_handle`.
148- // Returns function pointer or NULL if not present.
149-
150- char message[100 ];
151-
152- FARPROC func = GetProcAddress (lib_handle, func_name);
153- if (func == NULL ) {
154- sprintf (message, " Cannot load function %s" , func_name);
155- PyErr_SetString (PyExc_RuntimeError, message);
156- }
157- return func;
158- }
159-
160- int get_tcl (HMODULE hMod)
161- {
162- // Try to fill TCL global vars with function pointers. Return 0 for no
163- // functions found, 1 for all functions found, -1 for some but not all
164- // functions found.
165- TCL_CREATE_COMMAND = (Tcl_CreateCommand_t)
166- GetProcAddress (hMod, " Tcl_CreateCommand" );
167- if (TCL_CREATE_COMMAND == NULL ) { // Maybe not TCL module
168- return 0 ;
169- }
170- TCL_APPEND_RESULT = (Tcl_AppendResult_t) _dfunc (hMod, " Tcl_AppendResult" );
171- return (TCL_APPEND_RESULT == NULL ) ? -1 : 1 ;
172- }
173-
174- int get_tk (HMODULE hMod)
175- {
176- // Try to fill Tk global vars with function pointers. Return 0 for no
177- // functions found, 1 for all functions found, -1 for some but not all
178- // functions found.
179- TK_MAIN_WINDOW = (Tk_MainWindow_t)
180- GetProcAddress (hMod, " Tk_MainWindow" );
181- if (TK_MAIN_WINDOW == NULL ) { // Maybe not Tk module
182- return 0 ;
183- }
184- return // -1 if any remaining symbols are NULL
185- ((TK_FIND_PHOTO = (Tk_FindPhoto_t)
186- _dfunc (hMod, " Tk_FindPhoto" )) == NULL ) ||
187- ((TK_PHOTO_PUT_BLOCK_NO_COMPOSITE = (Tk_PhotoPutBlock_NoComposite_t)
188- _dfunc (hMod, " Tk_PhotoPutBlock_NoComposite" )) == NULL ) ||
189- ((TK_PHOTO_BLANK = (Tk_PhotoBlank_t)
190- _dfunc (hMod, " Tk_PhotoBlank" )) == NULL )
191- ? -1 : 1 ;
192- }
193134
194135void load_tkinter_funcs (void )
195136{
196137 // Load TCL and Tk functions by searching all modules in current process.
197- // Sets an error on failure.
198-
199138 HMODULE hMods[1024 ];
200139 HANDLE hProcess;
201140 DWORD cbNeeded;
202141 unsigned int i;
203- int found_tcl = 0 ;
204- int found_tk = 0 ;
205-
206142 // Returns pseudo-handle that does not need to be closed
207143 hProcess = GetCurrentProcess ();
208-
209144 // Iterate through modules in this process looking for TCL / Tk names
210145 if (EnumProcessModules (hProcess, hMods, sizeof (hMods), &cbNeeded)) {
211146 for (i = 0 ; i < (cbNeeded / sizeof (HMODULE)); i++) {
212- if (!found_tcl) {
213- found_tcl = get_tcl (hMods[i]);
214- if (found_tcl == -1 ) {
215- return ;
216- }
217- }
218- if (!found_tk) {
219- found_tk = get_tk (hMods[i]);
220- if (found_tk == -1 ) {
221- return ;
222- }
223- }
224- if (found_tcl && found_tk) {
147+ if (load_tk (hMods[i])) {
225148 return ;
226149 }
227150 }
228151 }
229-
230- if (found_tcl == 0 ) {
231- PyErr_SetString (PyExc_RuntimeError, " Could not find TCL routines" );
232- } else {
233- PyErr_SetString (PyExc_RuntimeError, " Could not find Tk routines" );
234- }
235- return ;
236152}
237153
238154#else // not Windows
@@ -243,54 +159,16 @@ void load_tkinter_funcs(void)
243159 * tkinter dynamic library (module).
244160 */
245161
246- #include < dlfcn.h>
247-
248- void *_dfunc (void *lib_handle, const char *func_name)
249- {
250- // Load function `func_name` from `lib_handle`.
251- // Set Python exception if we can't find `func_name` in `lib_handle`.
252- // Returns function pointer or NULL if not present.
253-
254- void * func;
255- // Reset errors.
256- dlerror ();
257- func = dlsym (lib_handle, func_name);
258- if (func == NULL ) {
259- PyErr_SetString (PyExc_RuntimeError, dlerror ());
260- }
261- return func;
262- }
263-
264- int _func_loader (void *lib)
265- {
266- // Fill global function pointers from dynamic lib.
267- // Return 1 if any pointer is NULL, 0 otherwise.
268- return
269- ((TCL_CREATE_COMMAND = (Tcl_CreateCommand_t)
270- _dfunc (lib, " Tcl_CreateCommand" )) == NULL ) ||
271- ((TCL_APPEND_RESULT = (Tcl_AppendResult_t)
272- _dfunc (lib, " Tcl_AppendResult" )) == NULL ) ||
273- ((TK_MAIN_WINDOW = (Tk_MainWindow_t)
274- _dfunc (lib, " Tk_MainWindow" )) == NULL ) ||
275- ((TK_FIND_PHOTO = (Tk_FindPhoto_t)
276- _dfunc (lib, " Tk_FindPhoto" )) == NULL ) ||
277- ((TK_PHOTO_PUT_BLOCK_NO_COMPOSITE = (Tk_PhotoPutBlock_NoComposite_t)
278- _dfunc (lib, " Tk_PhotoPutBlock_NoComposite" )) == NULL ) ||
279- ((TK_PHOTO_BLANK = (Tk_PhotoBlank_t)
280- _dfunc (lib, " Tk_PhotoBlank" )) == NULL );
281- }
282-
283162void load_tkinter_funcs (void )
284163{
285164 // Load tkinter global funcs from tkinter compiled module.
286- // Sets an error on failure.
287165 void *main_program, *tkinter_lib;
288166 PyObject *module = NULL , *py_path = NULL , *py_path_b = NULL ;
289167 char *path;
290168
291169 // Try loading from the main program namespace first.
292170 main_program = dlopen (NULL , RTLD_LAZY);
293- if (_func_loader (main_program) == 0 ) {
171+ if (load_tk (main_program)) {
294172 goto exit;
295173 }
296174 // Clear exception triggered when we didn't find symbols above.
@@ -313,7 +191,7 @@ void load_tkinter_funcs(void)
313191 PyErr_SetString (PyExc_RuntimeError, dlerror ());
314192 goto exit;
315193 }
316- _func_loader (tkinter_lib);
194+ load_tk (tkinter_lib);
317195 // dlclose is safe because tkinter has been imported.
318196 dlclose (tkinter_lib);
319197 goto exit;
@@ -331,5 +209,14 @@ static PyModuleDef _tkagg_module = {
331209PyMODINIT_FUNC PyInit__tkagg (void )
332210{
333211 load_tkinter_funcs ();
334- return PyErr_Occurred () ? NULL : PyModule_Create (&_tkagg_module);
212+ if (PyErr_Occurred ()) {
213+ return NULL ;
214+ } else if (!TK_FIND_PHOTO) {
215+ PyErr_SetString (PyExc_RuntimeError, " Failed to load Tk_FindPhoto" );
216+ return NULL ;
217+ } else if (!TK_PHOTO_PUT_BLOCK_NO_COMPOSITE) {
218+ PyErr_SetString (PyExc_RuntimeError, " Failed to load Tk_PhotoPutBlock_NoComposite" );
219+ return NULL ;
220+ }
221+ return PyModule_Create (&_tkagg_module);
335222}
0 commit comments