[Image-SIG] Adventures building zlib and _imaging
Roger Burnham
rburnham@cri-inc.com
Wed, 26 May 1999 16:41:13 GMT
I finally took the plunge and upgraded CRI's production software to the
latest versions of Python (1.5.2), PythonWin (build 125), Numeric
(LLNLDistribution11), zlib (113, with buildzlib113dll.zip, from
http://www.winimage.com/zLibDll/build.html), jpeg (6b), and Imaging
(Imaging-1.0b1). This is on Win95 (4.00.950 B) using VC++ 6.0
(no service packs).
The problems:
Including windows.h after Imaging.h causes the error:
C:\vc\VC98\INCLUDE\basetsd.h(33) : error C2632: 'int' followed by 'int' is illegal
The fix is to
#undef INT32
#undef UINT32
before including windows.h, in map.c and ImDib.h. Neither map.c, nor any
file that includes ImDib.h directly reference either symbol.
When linking _imaging, names exported by zlib are not found due
to name mangling in zlib. The fix was in zconf.h.
Change:
/* Compile with -DZLIB_DLL for Windows DLL support */
#if defined(ZLIB_DLL)
# if defined(_WINDOWS) || defined(WINDOWS)
# ifdef FAR
# undef FAR
# endif
# include <windows.h>
# define ZEXPORT WINAPI
to
/* Compile with -DZLIB_DLL for Windows DLL support */
/* WINAPI */
#if defined(ZLIB_DLL)
# if defined(_WINDOWS) || defined(WINDOWS)
# ifdef FAR
# undef FAR
# endif
# include <windows.h>
# define ZEXPORT FAR _cdecl
to get the undecorated names exported.
Now everything builds ok (zlibmodule also, which links to the static
version of zlib).
And now a hack I added to Imaging... I really like the way Numeric
exports its API to other C/C++ programs via the import_array macro. As
I also use Imaging from C extensions, I've added the same to Imaging.
Imaging.c:
Remove
typedef struct {
PyObject_HEAD
Imaging image;
} ImagingObject;
and add #define _IMAGING_MODULE before including Imaging.h
Change init_imaging to:
init_imaging()
{
PyObject *m, *d;
static void *PyImaging_API[PyImaging_API_pointers];
/* Patch object type */
Imaging_Type.ob_type = &PyType_Type;
m = Py_InitModule("_imaging", functions);
d = PyModule_GetDict(m);
/* Initialize C API pointer arrays and store them in module */
PyImaging_API[PyImaging_Type_NUM] = (void *)&Imaging_Type;
PyDict_SetItemString(d, "_IMAGING_API",
PyCObject_FromVoidPtr((void *)PyImaging_API, NULL));
/* Check for errors */
if (PyErr_Occurred())
Py_FatalError("can't initialize module _imaging");
}
To Imaging.h add
#define PyImaging_Type_NUM 0
#define PyImaging_API_pointers 1
#if defined (_IMAGING_MODULE) || defined (_IMAGING_USER)
typedef struct {
PyObject_HEAD
Imaging image;
} ImagingObject;
#endif
#ifdef _IMAGING_USER
void **PyImaging_API;
#define PyImaging_Check(op) \
((op)->ob_type == (PyTypeObject *)PyImaging_API[PyImaging_Type_NUM])
#define Imaging_Type *(PyTypeObject *)PyImaging_API[PyImaging_Type_NUM]
#define import_imaging() \
{ \
PyObject *_pilMod = PyImport_ImportModule("_imaging"); \
if (_pilMod != NULL) { \
PyObject *module_dict = PyModule_GetDict(_pilMod); \
PyObject *c_api_object = PyDict_GetItemString(module_dict, "_IMAGING_API"); \
if (PyCObject_Check(c_api_object)) { \
PyImaging_API = (void **)PyCObject_AsVoidPtr(c_api_object); \
} \
} \
}
#endif
after the typedef struct's near the top.
Now, in your C/C++ code, before including Imaging.h
#define _IMAGING_USER
and in your modules init, add
import_imaging();
Not quite as clean as the Numeric method, but works,
Any chance of getting this or something like it in the Imaging distribution?
Thanks to all of the authors of the above software, quite a powerful lot of
stuff for a mornings work!
If any one wants the VC++ project files for Imaging, drop me a line...
Cheers,
Roger Burnham
Cambridge Research & Instrumentation
rburnham@cri-inc.com
http://www.cri-inc.com/
http://starship.python.net/crew/roger/
PGP Key: http://www.nai.com/default_pgp.asp
PGP Fingerprint: 5372 729A 9557 5F36 177F 084A 6C64 BE27 0BC4 CF2D