[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