mirror of
				https://github.com/python-pillow/Pillow.git
				synced 2025-11-04 01:47:47 +03:00 
			
		
		
		
	
		
			
				
	
	
		
			478 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			478 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/*
 | 
						|
 * The Python Imaging Library.
 | 
						|
 * $Id$
 | 
						|
 *
 | 
						|
 * TK interface for Python Imaging objects
 | 
						|
 *
 | 
						|
 * Copies (parts of) a named display memory to a photo image object.
 | 
						|
 * Also contains code to create an display memory.  Under Tk, a
 | 
						|
 * display memory is simply an "L" or "RGB" image memory that is
 | 
						|
 * allocated in a single block.
 | 
						|
 *
 | 
						|
 * To use this module, import the _imagingtk module (ImageTk does
 | 
						|
 * this for you).
 | 
						|
 *
 | 
						|
 * If you're using Python in an embedded context, you can add the
 | 
						|
 * following lines to your Tcl_AppInit function (in tkappinit.c)
 | 
						|
 * instead.  Put them after the calls to Tcl_Init and Tk_Init:
 | 
						|
 *
 | 
						|
 *	{
 | 
						|
 *          extern void TkImaging_Init(Tcl_Interp* interp);
 | 
						|
 *          TkImaging_Init(interp);
 | 
						|
 *      }
 | 
						|
 *
 | 
						|
 * This registers a Tcl command called "PyImagingPhoto", which is used
 | 
						|
 * to communicate between PIL and Tk's PhotoImage handler.
 | 
						|
 *
 | 
						|
 | 
						|
 * History:
 | 
						|
 * 1995-09-12 fl  Created
 | 
						|
 * 1996-04-08 fl  Ready for release
 | 
						|
 * 1997-05-09 fl  Use command instead of image type
 | 
						|
 * 2001-03-18 fl  Initialize alpha layer pointer (struct changed in 8.3)
 | 
						|
 * 2003-04-23 fl  Fixed building for Tk 8.4.1 and later (Jack Jansen)
 | 
						|
 * 2004-06-24 fl  Fixed building for Tk 8.4.6 and later.
 | 
						|
 *
 | 
						|
 * Copyright (c) 1997-2004 by Secret Labs AB
 | 
						|
 * Copyright (c) 1995-2004 by Fredrik Lundh
 | 
						|
 *
 | 
						|
 * See the README file for information on usage and redistribution.
 | 
						|
 */
 | 
						|
 | 
						|
#include "Imaging.h"
 | 
						|
#include "_tkmini.h"
 | 
						|
 | 
						|
#include <stdlib.h>
 | 
						|
 | 
						|
/*
 | 
						|
 * Global vars for Tcl / Tk functions.  We load these symbols from the tkinter
 | 
						|
 * extension module or loaded Tcl / Tk libraries at run-time.
 | 
						|
 */
 | 
						|
static int TK_LT_85 = 0;
 | 
						|
static Tcl_CreateCommand_t TCL_CREATE_COMMAND;
 | 
						|
static Tcl_AppendResult_t TCL_APPEND_RESULT;
 | 
						|
static Tk_FindPhoto_t TK_FIND_PHOTO;
 | 
						|
static Tk_PhotoGetImage_t TK_PHOTO_GET_IMAGE;
 | 
						|
static Tk_PhotoPutBlock_84_t TK_PHOTO_PUT_BLOCK_84;
 | 
						|
static Tk_PhotoSetSize_84_t TK_PHOTO_SET_SIZE_84;
 | 
						|
static Tk_PhotoPutBlock_85_t TK_PHOTO_PUT_BLOCK_85;
 | 
						|
 | 
						|
static Imaging
 | 
						|
ImagingFind(const char* name)
 | 
						|
{
 | 
						|
    Py_ssize_t id;
 | 
						|
 | 
						|
    /* FIXME: use CObject instead? */
 | 
						|
#if defined(_MSC_VER) && defined(_WIN64)
 | 
						|
    id = _atoi64(name);
 | 
						|
#else
 | 
						|
    id = atol(name);
 | 
						|
#endif
 | 
						|
    if (!id)
 | 
						|
	return NULL;
 | 
						|
 | 
						|
    return (Imaging) id;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
static int
 | 
						|
PyImagingPhotoPut(ClientData clientdata, Tcl_Interp* interp,
 | 
						|
               int argc, const char **argv)
 | 
						|
{
 | 
						|
    Imaging im;
 | 
						|
    Tk_PhotoHandle photo;
 | 
						|
    Tk_PhotoImageBlock block;
 | 
						|
 | 
						|
    if (argc != 3) {
 | 
						|
        TCL_APPEND_RESULT(interp, "usage: ", argv[0],
 | 
						|
                         " destPhoto srcImage", (char *) NULL);
 | 
						|
        return TCL_ERROR;
 | 
						|
    }
 | 
						|
 | 
						|
    /* get Tcl PhotoImage handle */
 | 
						|
    photo = TK_FIND_PHOTO(interp, argv[1]);
 | 
						|
    if (photo == NULL) {
 | 
						|
        TCL_APPEND_RESULT(
 | 
						|
            interp, "destination photo must exist", (char *) NULL
 | 
						|
            );
 | 
						|
        return TCL_ERROR;
 | 
						|
    }
 | 
						|
 | 
						|
    /* get PIL Image handle */
 | 
						|
    im = ImagingFind(argv[2]);
 | 
						|
    if (!im) {
 | 
						|
        TCL_APPEND_RESULT(interp, "bad name", (char*) NULL);
 | 
						|
        return TCL_ERROR;
 | 
						|
    }
 | 
						|
    if (!im->block) {
 | 
						|
        TCL_APPEND_RESULT(interp, "bad display memory", (char*) NULL);
 | 
						|
        return TCL_ERROR;
 | 
						|
    }
 | 
						|
 | 
						|
    /* Active region */
 | 
						|
#if 0
 | 
						|
    if (src_xoffset + xsize > im->xsize)
 | 
						|
	xsize = im->xsize - src_xoffset;
 | 
						|
    if (src_yoffset + ysize > im->ysize)
 | 
						|
	ysize = im->ysize - src_yoffset;
 | 
						|
    if (xsize < 0 || ysize < 0
 | 
						|
	|| src_xoffset >= im->xsize
 | 
						|
	|| src_yoffset >= im->ysize)
 | 
						|
	return TCL_OK;
 | 
						|
#endif
 | 
						|
 | 
						|
    /* Mode */
 | 
						|
 | 
						|
    if (strcmp(im->mode, "1") == 0 || strcmp(im->mode, "L") == 0) {
 | 
						|
	block.pixelSize = 1;
 | 
						|
	block.offset[0] = block.offset[1] = block.offset[2] = 0;
 | 
						|
    } else if (strncmp(im->mode, "RGB", 3) == 0) {
 | 
						|
	block.pixelSize = 4;
 | 
						|
	block.offset[0] = 0;
 | 
						|
	block.offset[1] = 1;
 | 
						|
	block.offset[2] = 2;
 | 
						|
        if (strcmp(im->mode, "RGBA") == 0)
 | 
						|
            block.offset[3] = 3; /* alpha (or reserved, under 8.2) */
 | 
						|
        else
 | 
						|
            block.offset[3] = 0; /* no alpha */
 | 
						|
    } else {
 | 
						|
        TCL_APPEND_RESULT(interp, "Bad mode", (char*) NULL);
 | 
						|
	return TCL_ERROR;
 | 
						|
    }
 | 
						|
 | 
						|
    block.width = im->xsize;
 | 
						|
    block.height = im->ysize;
 | 
						|
    block.pitch = im->linesize;
 | 
						|
    block.pixelPtr = (unsigned char*) im->block;
 | 
						|
#if 0
 | 
						|
    block.pixelPtr = (unsigned char*) im->block +
 | 
						|
	             src_yoffset * im->linesize +
 | 
						|
	             src_xoffset * im->pixelsize;
 | 
						|
#endif
 | 
						|
 | 
						|
    if (TK_LT_85) { /* Tk 8.4 */
 | 
						|
        TK_PHOTO_PUT_BLOCK_84(photo, &block, 0, 0, block.width, block.height,
 | 
						|
                TK_PHOTO_COMPOSITE_SET);
 | 
						|
        if (strcmp(im->mode, "RGBA") == 0)
 | 
						|
            /* Tk workaround: we need apply ToggleComplexAlphaIfNeeded */
 | 
						|
            /* (fixed in Tk 8.5a3) */
 | 
						|
            TK_PHOTO_SET_SIZE_84(photo, block.width, block.height);
 | 
						|
    } else {
 | 
						|
        /* Tk >=8.5 */
 | 
						|
        TK_PHOTO_PUT_BLOCK_85(interp, photo, &block, 0, 0, block.width,
 | 
						|
                block.height, TK_PHOTO_COMPOSITE_SET);
 | 
						|
    }
 | 
						|
 | 
						|
    return TCL_OK;
 | 
						|
}
 | 
						|
 | 
						|
/*  Warning -- this does not work at all */
 | 
						|
static int
 | 
						|
PyImagingPhotoGet(ClientData clientdata, Tcl_Interp* interp,
 | 
						|
               int argc, const char **argv)
 | 
						|
{
 | 
						|
    Tk_PhotoHandle photo;
 | 
						|
    Tk_PhotoImageBlock block;
 | 
						|
 | 
						|
    if (argc != 2) {
 | 
						|
        TCL_APPEND_RESULT(interp, "usage: ", argv[0],
 | 
						|
                         " srcPhoto", (char *) NULL);
 | 
						|
        return TCL_ERROR;
 | 
						|
    }
 | 
						|
 | 
						|
    /* get Tcl PhotoImage handle */
 | 
						|
    photo = TK_FIND_PHOTO(interp, argv[1]);
 | 
						|
    if (photo == NULL) {
 | 
						|
        TCL_APPEND_RESULT(
 | 
						|
            interp, "source photo must exist", (char *) NULL
 | 
						|
            );
 | 
						|
        return TCL_ERROR;
 | 
						|
    }
 | 
						|
 | 
						|
    TK_PHOTO_GET_IMAGE(photo, &block);
 | 
						|
 | 
						|
    printf("pixelPtr = %p\n", block.pixelPtr);
 | 
						|
    printf("width = %d\n", block.width);
 | 
						|
    printf("height = %d\n", block.height);
 | 
						|
    printf("pitch = %d\n", block.pitch);
 | 
						|
    printf("pixelSize = %d\n", block.pixelSize);
 | 
						|
    printf("offset = %d %d %d %d\n", block.offset[0], block.offset[1],
 | 
						|
           block.offset[2], block.offset[3]);
 | 
						|
 | 
						|
    TCL_APPEND_RESULT(
 | 
						|
        interp, "this function is not yet supported", (char *) NULL
 | 
						|
        );
 | 
						|
 | 
						|
    return TCL_ERROR;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
void
 | 
						|
TkImaging_Init(Tcl_Interp* interp)
 | 
						|
{
 | 
						|
    TCL_CREATE_COMMAND(interp, "PyImagingPhoto", PyImagingPhotoPut,
 | 
						|
                      (ClientData) 0, (Tcl_CmdDeleteProc*) NULL);
 | 
						|
    TCL_CREATE_COMMAND(interp, "PyImagingPhotoGet", PyImagingPhotoGet,
 | 
						|
                      (ClientData) 0, (Tcl_CmdDeleteProc*) NULL);
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
 * Functions to fill global Tcl / Tk function pointers by dynamic loading
 | 
						|
 */
 | 
						|
 | 
						|
#define TKINTER_FINDER "PIL._tkinter_finder"
 | 
						|
 | 
						|
#if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
 | 
						|
 | 
						|
/*
 | 
						|
 * On Windows, we can't load the tkinter module to get the Tcl or Tk symbols,
 | 
						|
 * because Windows does not load symbols into the library name-space of
 | 
						|
 * importing modules. So, knowing that tkinter has already been imported by
 | 
						|
 * Python, we scan all modules in the running process for the Tcl and Tk
 | 
						|
 * function names.
 | 
						|
 */
 | 
						|
#include <windows.h>
 | 
						|
#define PSAPI_VERSION 1
 | 
						|
#include <psapi.h>
 | 
						|
/* Must be linked with 'psapi' library */
 | 
						|
 | 
						|
#if PY_VERSION_HEX >= 0x03000000
 | 
						|
#define TKINTER_PKG "tkinter"
 | 
						|
#else
 | 
						|
#define TKINTER_PKG "Tkinter"
 | 
						|
#endif
 | 
						|
 | 
						|
FARPROC _dfunc(HMODULE lib_handle, const char *func_name)
 | 
						|
{
 | 
						|
    /*
 | 
						|
     * Load function `func_name` from `lib_handle`.
 | 
						|
     * Set Python exception if we can't find `func_name` in `lib_handle`.
 | 
						|
     * Returns function pointer or NULL if not present.
 | 
						|
    */
 | 
						|
 | 
						|
    char message[100];
 | 
						|
 | 
						|
    FARPROC func = GetProcAddress(lib_handle, func_name);
 | 
						|
    if (func == NULL) {
 | 
						|
        sprintf(message, "Cannot load function %s", func_name);
 | 
						|
        PyErr_SetString(PyExc_RuntimeError, message);
 | 
						|
    }
 | 
						|
    return func;
 | 
						|
}
 | 
						|
 | 
						|
int get_tcl(HMODULE hMod)
 | 
						|
{
 | 
						|
    /*
 | 
						|
     * Try to fill Tcl global vars with function pointers. Return 0 for no
 | 
						|
     * functions found, 1 for all functions found, -1 for some but not all
 | 
						|
     * functions found.
 | 
						|
     */
 | 
						|
 | 
						|
    if ((TCL_CREATE_COMMAND = (Tcl_CreateCommand_t)
 | 
						|
        GetProcAddress(hMod, "Tcl_CreateCommand")) == NULL) {
 | 
						|
        return 0; /* Maybe not Tcl module */
 | 
						|
    }
 | 
						|
    return ((TCL_APPEND_RESULT = (Tcl_AppendResult_t) _dfunc(hMod,
 | 
						|
            "Tcl_AppendResult")) == NULL) ? -1 : 1;
 | 
						|
}
 | 
						|
 | 
						|
int get_tk(HMODULE hMod)
 | 
						|
{
 | 
						|
    /*
 | 
						|
     * Try to fill Tk global vars with function pointers. Return 0 for no
 | 
						|
     * functions found, 1 for all functions found, -1 for some but not all
 | 
						|
     * functions found.
 | 
						|
     */
 | 
						|
 | 
						|
    FARPROC func = GetProcAddress(hMod, "Tk_PhotoPutBlock");
 | 
						|
    if (func == NULL) {  /* Maybe not Tk module */
 | 
						|
        return 0;
 | 
						|
    }
 | 
						|
    if ((TK_PHOTO_GET_IMAGE = (Tk_PhotoGetImage_t)
 | 
						|
                _dfunc(hMod, "Tk_PhotoGetImage")) == NULL) { return -1; };
 | 
						|
    if ((TK_FIND_PHOTO = (Tk_FindPhoto_t)
 | 
						|
                _dfunc(hMod, "Tk_FindPhoto")) == NULL) { return -1; };
 | 
						|
    TK_LT_85 = GetProcAddress(hMod, "Tk_PhotoPutBlock_Panic") == NULL;
 | 
						|
    /* Tk_PhotoPutBlock_Panic defined as of 8.5.0 */
 | 
						|
    if (TK_LT_85) {
 | 
						|
        TK_PHOTO_PUT_BLOCK_84 = (Tk_PhotoPutBlock_84_t) func;
 | 
						|
        return ((TK_PHOTO_SET_SIZE_84 = (Tk_PhotoSetSize_84_t)
 | 
						|
                    _dfunc(hMod, "Tk_PhotoSetSize")) == NULL) ? -1 : 1;
 | 
						|
    }
 | 
						|
    TK_PHOTO_PUT_BLOCK_85 = (Tk_PhotoPutBlock_85_t) func;
 | 
						|
    return 1;
 | 
						|
}
 | 
						|
 | 
						|
int load_tkinter_funcs(void)
 | 
						|
{
 | 
						|
    /*
 | 
						|
     * Load Tcl and Tk functions by searching all modules in current process.
 | 
						|
     * Return 0 for success, non-zero for failure.
 | 
						|
     */
 | 
						|
 | 
						|
    HMODULE hMods[1024];
 | 
						|
    HANDLE hProcess;
 | 
						|
    DWORD cbNeeded;
 | 
						|
    unsigned int i;
 | 
						|
    int found_tcl = 0;
 | 
						|
    int found_tk = 0;
 | 
						|
 | 
						|
    /* First load tkinter module to make sure libraries are loaded */
 | 
						|
    PyObject *pModule = PyImport_ImportModule(TKINTER_PKG);
 | 
						|
    if (pModule == NULL) {
 | 
						|
        return 1;
 | 
						|
    }
 | 
						|
    Py_DECREF(pModule);
 | 
						|
 | 
						|
    /* Returns pseudo-handle that does not need to be closed */
 | 
						|
    hProcess = GetCurrentProcess();
 | 
						|
 | 
						|
    /* Iterate through modules in this process looking for Tcl / Tk names */
 | 
						|
    if (EnumProcessModules(hProcess, hMods, sizeof(hMods), &cbNeeded)) {
 | 
						|
        for (i = 0; i < (cbNeeded / sizeof(HMODULE)); i++) {
 | 
						|
            if (!found_tcl) {
 | 
						|
                found_tcl = get_tcl(hMods[i]);
 | 
						|
                if (found_tcl == -1) {
 | 
						|
                    return 1;
 | 
						|
                }
 | 
						|
            }
 | 
						|
            if (!found_tk) {
 | 
						|
                found_tk = get_tk(hMods[i]);
 | 
						|
                if (found_tk == -1) {
 | 
						|
                    return 1;
 | 
						|
                }
 | 
						|
            }
 | 
						|
            if (found_tcl && found_tk) {
 | 
						|
                return 0;
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    if (found_tcl == 0) {
 | 
						|
        PyErr_SetString(PyExc_RuntimeError, "Could not find Tcl routines");
 | 
						|
    } else {
 | 
						|
        PyErr_SetString(PyExc_RuntimeError, "Could not find Tk routines");
 | 
						|
    }
 | 
						|
    return 1;
 | 
						|
}
 | 
						|
 | 
						|
#else  /* not Windows */
 | 
						|
 | 
						|
/*
 | 
						|
 * On Unix, we can get the Tcl and Tk symbols from the tkinter module, because
 | 
						|
 * tkinter uses these symbols, and the symbols are therefore visible in the
 | 
						|
 * tkinter dynamic library (module).
 | 
						|
 */
 | 
						|
 | 
						|
/* From module __file__ attribute to char *string for dlopen. */
 | 
						|
#if PY_VERSION_HEX >= 0x03000000
 | 
						|
char *fname2char(PyObject *fname)
 | 
						|
{
 | 
						|
    PyObject* bytes;
 | 
						|
    bytes = PyUnicode_EncodeFSDefault(fname);
 | 
						|
    if (bytes == NULL) {
 | 
						|
        return NULL;
 | 
						|
    }
 | 
						|
    return PyBytes_AsString(bytes);
 | 
						|
}
 | 
						|
#else
 | 
						|
#define fname2char(s) (PyString_AsString(s))
 | 
						|
#endif
 | 
						|
 | 
						|
#include <dlfcn.h>
 | 
						|
 | 
						|
void *_dfunc(void *lib_handle, const char *func_name)
 | 
						|
{
 | 
						|
    /*
 | 
						|
     * Load function `func_name` from `lib_handle`.
 | 
						|
     * Set Python exception if we can't find `func_name` in `lib_handle`.
 | 
						|
     * Returns function pointer or NULL if not present.
 | 
						|
     */
 | 
						|
 | 
						|
    void* func;
 | 
						|
    /* Reset errors. */
 | 
						|
    dlerror();
 | 
						|
    func = dlsym(lib_handle, func_name);
 | 
						|
    if (func == NULL) {
 | 
						|
        const char *error = dlerror();
 | 
						|
        PyErr_SetString(PyExc_RuntimeError, error);
 | 
						|
    }
 | 
						|
    return func;
 | 
						|
}
 | 
						|
 | 
						|
int _func_loader(void *lib)
 | 
						|
{
 | 
						|
    /*
 | 
						|
     * Fill global function pointers from dynamic lib.
 | 
						|
     * Return 1 if any pointer is NULL, 0 otherwise.
 | 
						|
     */
 | 
						|
 | 
						|
    if ((TCL_CREATE_COMMAND = (Tcl_CreateCommand_t)
 | 
						|
            _dfunc(lib, "Tcl_CreateCommand")) == NULL) { return 1; }
 | 
						|
    if ((TCL_APPEND_RESULT = (Tcl_AppendResult_t) _dfunc(lib,
 | 
						|
                "Tcl_AppendResult")) == NULL) { return 1; }
 | 
						|
    if ((TK_PHOTO_GET_IMAGE = (Tk_PhotoGetImage_t)
 | 
						|
                _dfunc(lib, "Tk_PhotoGetImage")) == NULL) { return 1; }
 | 
						|
    if ((TK_FIND_PHOTO = (Tk_FindPhoto_t)
 | 
						|
                _dfunc(lib, "Tk_FindPhoto")) == NULL) { return 1; }
 | 
						|
    /* Tk_PhotoPutBlock_Panic defined as of 8.5.0 */
 | 
						|
    TK_LT_85 = (dlsym(lib, "Tk_PhotoPutBlock_Panic") == NULL);
 | 
						|
    if (TK_LT_85) {
 | 
						|
        return (((TK_PHOTO_PUT_BLOCK_84 = (Tk_PhotoPutBlock_84_t)
 | 
						|
                        _dfunc(lib, "Tk_PhotoPutBlock")) == NULL) ||
 | 
						|
                ((TK_PHOTO_SET_SIZE_84 = (Tk_PhotoSetSize_84_t)
 | 
						|
                  _dfunc(lib, "Tk_PhotoSetSize")) == NULL));
 | 
						|
    }
 | 
						|
    return ((TK_PHOTO_PUT_BLOCK_85 = (Tk_PhotoPutBlock_85_t)
 | 
						|
                _dfunc(lib, "Tk_PhotoPutBlock")) == NULL);
 | 
						|
}
 | 
						|
 | 
						|
int load_tkinter_funcs(void)
 | 
						|
{
 | 
						|
    /*
 | 
						|
     * Load tkinter global funcs from tkinter compiled module.
 | 
						|
     * Return 0 for success, non-zero for failure.
 | 
						|
     */
 | 
						|
 | 
						|
    int ret = -1;
 | 
						|
    void *main_program, *tkinter_lib;
 | 
						|
    char *tkinter_libname;
 | 
						|
    PyObject *pModule = NULL, *pString = NULL;
 | 
						|
 | 
						|
    /* Try loading from the main program namespace first */
 | 
						|
    main_program = dlopen(NULL, RTLD_LAZY);
 | 
						|
    if (_func_loader(main_program) == 0) {
 | 
						|
        return 0;
 | 
						|
    }
 | 
						|
    /* Clear exception triggered when we didn't find symbols above */
 | 
						|
    PyErr_Clear();
 | 
						|
 | 
						|
    /* Now try finding the tkinter compiled module */
 | 
						|
    pModule = PyImport_ImportModule(TKINTER_FINDER);
 | 
						|
    if (pModule == NULL) {
 | 
						|
        goto exit;
 | 
						|
    }
 | 
						|
    pString = PyObject_GetAttrString(pModule, "TKINTER_LIB");
 | 
						|
    if (pString == NULL) {
 | 
						|
        goto exit;
 | 
						|
    }
 | 
						|
    tkinter_libname = fname2char(pString);
 | 
						|
    if (tkinter_libname == NULL) {
 | 
						|
        goto exit;
 | 
						|
    }
 | 
						|
    tkinter_lib = dlopen(tkinter_libname, RTLD_LAZY);
 | 
						|
    if (tkinter_lib == NULL) {
 | 
						|
        PyErr_SetString(PyExc_RuntimeError,
 | 
						|
                "Cannot dlopen tkinter module file");
 | 
						|
        goto exit;
 | 
						|
    }
 | 
						|
    ret = _func_loader(tkinter_lib);
 | 
						|
    /* dlclose probably safe because tkinter has been imported. */
 | 
						|
    dlclose(tkinter_lib);
 | 
						|
exit:
 | 
						|
    Py_XDECREF(pModule);
 | 
						|
    Py_XDECREF(pString);
 | 
						|
    return ret;
 | 
						|
}
 | 
						|
#endif /* end not Windows */
 |