Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 038a25e

Browse filesBrowse 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 038a25e
Copy full SHA for 038a25e

File tree

Expand file treeCollapse file tree

2 files changed

+32
-173
lines changed
Filter options
Expand file treeCollapse file tree

2 files changed

+32
-173
lines changed

‎src/_tkagg.cpp

Copy file name to clipboardExpand all lines: src/_tkagg.cpp
+31-144Lines 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

Copy file name to clipboardExpand all lines: src/_tkmini.h
+1-29Lines changed: 1 addition & 29 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

@@ -108,20 +87,13 @@ typedef struct Tk_PhotoImageBlock
10887
} Tk_PhotoImageBlock;
10988

11089
/* Typedefs derived from function signatures in Tk header */
111-
/* Tk_MainWindow */
112-
typedef Tk_Window (*Tk_MainWindow_t) (Tcl_Interp *interp);
90+
/* Tk_FindPhoto typedef */
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);
121-
122-
/*
123-
* end block for C++
124-
*/
12597

12698
#ifdef __cplusplus
12799
}

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.