Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 2277be8

Browse files
committed
Simplify tk loader.
We don't need to load tcl function pointers anymore; everything now comes from tk's shared library so the shared object search is also simpler. Also remove some more remnants of the now-removed tcl-based command: IMG_FORMAT, BBOX_FORMAT, TkappObject.
1 parent 663a429 commit 2277be8

File tree

2 files changed

+31
-168
lines changed

2 files changed

+31
-168
lines changed

src/_tkagg.cpp

Lines changed: 31 additions & 144 deletions
Original file line numberDiff line numberDiff line change
@@ -9,42 +9,24 @@
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;
4528
static Tk_FindPhoto_t TK_FIND_PHOTO;
4629
static Tk_PhotoPutBlock_NoComposite_t TK_PHOTO_PUT_BLOCK_NO_COMPOSITE;
47-
static Tk_PhotoBlank_t TK_PHOTO_BLANK;
4830

4931
static PyObject *mpl_tk_blit(PyObject *self, PyObject *args)
5032
{
@@ -118,7 +100,6 @@ Win32_SetForegroundWindow(PyObject *module, PyObject *args)
118100
#endif
119101

120102
static 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

194135
void 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-
283162
void 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 = {
331209
PyMODINIT_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
}

src/_tkmini.h

Lines changed: 0 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -66,34 +66,13 @@
6666
extern "C" {
6767
#endif
6868

69-
/* Tcl header excerpts */
70-
#define TCL_OK 0
71-
#define TCL_ERROR 1
72-
7369
/*
7470
* Users of versions of Tcl >= 8.6 encouraged to tread Tcl_Interp as an opaque
7571
* pointer. The following definition results when TCL_NO_DEPRECATED defined.
7672
*/
7773
typedef struct Tcl_Interp Tcl_Interp;
7874

79-
typedef struct Tcl_Command_ *Tcl_Command;
80-
typedef void *ClientData;
81-
82-
typedef int (Tcl_CmdProc) (ClientData clientData, Tcl_Interp
83-
*interp, int argc, const char *argv[]);
84-
typedef void (Tcl_CmdDeleteProc) (ClientData clientData);
85-
86-
/* Typedefs derived from function signatures in Tcl header */
87-
/* Tcl_CreateCommand */
88-
typedef Tcl_Command (*Tcl_CreateCommand_t)(Tcl_Interp *interp,
89-
const char *cmdName, Tcl_CmdProc *proc,
90-
ClientData clientData,
91-
Tcl_CmdDeleteProc *deleteProc);
92-
/* Tcl_AppendResult */
93-
typedef void (*Tcl_AppendResult_t) (Tcl_Interp *interp, ...);
94-
9575
/* Tk header excerpts */
96-
typedef struct Tk_Window_ *Tk_Window;
9776

9877
typedef void *Tk_PhotoHandle;
9978

@@ -109,15 +88,12 @@ typedef struct Tk_PhotoImageBlock
10988

11089
/* Typedefs derived from function signatures in Tk header */
11190
/* Tk_MainWindow */
112-
typedef Tk_Window (*Tk_MainWindow_t) (Tcl_Interp *interp);
11391
typedef Tk_PhotoHandle (*Tk_FindPhoto_t) (Tcl_Interp *interp, const char
11492
*imageName);
11593
/* Tk_PhotoPutBLock_NoComposite typedef */
11694
typedef void (*Tk_PhotoPutBlock_NoComposite_t) (Tk_PhotoHandle handle,
11795
Tk_PhotoImageBlock *blockPtr, int x, int y,
11896
int width, int height);
119-
/* Tk_PhotoBlank */
120-
typedef void (*Tk_PhotoBlank_t) (Tk_PhotoHandle handle);
12197

12298
/*
12399
* end block for C++

0 commit comments

Comments
 (0)