[Zlib-devel] zlib 1.2.0.1 available for testing

Cosmin Truta cosmin at cs.toronto.edu
Wed Mar 19 20:25:01 EST 2003


On Mon, 17 Mar 2003, Mark Adler wrote:

> You can get the special St. Patty's Day edition of zlib, version
> 1.2.0.1 here:
>
>      http://www.alumni.caltech.edu/~madler/zlib-1.2.0.1.tar.gz

Hi,

I looked at the package, and the first thing I said was "Oh, no, you
enabled the ZLIB_DLL madness by default!..."

[This email is long, but it's only because I wish so badly to be
 convincing...]

You can search, for example, in the png-implement discussion archive
at http://pmt.sourceforge.net/mailing-lists/png-implement/
You can't imagine how many problems we had in there because of it.
The situation is somewhat easier in zlib as long as one does not use
callbacks (like user-supplied zalloc) but if one does, and does not
decorate the callbacks properly with ZEXPORT, the __stdcall vs. __cdecl
nightmare (and not only) will have to start.

First of all, if you don't do anything to the source files (just have
an empty ZEXPORT), you can build a working DLL just fine. You may start
adding a __declspec(dllexport) or __declspec(dllimport), according to
the circumstance, and save a few CPU cycles per ZEXPORT function call
from outside (without affecting DLL-internal calls) -- which is really
nothing compared to what's happening inside zlib -- but this may break
the whole stuff whenever the DLL-specific code is triggered where it
isn't supposed to.

My suggestion to stop making ZLIB_DLL a default works simply because a
zlib.def file exists.

There are many other issues. I see that the shared zlib library is built
by default on Unix, which may be ok. Building a DLL by default on Win32,
on the other hand, is not ok, without indicating which C runtime library
is being used. In other words, a ZLIB.DLL linked with the dynamic CRTL
library MSVCRT.DLL cannot run properly with an app that links to the
static-singlethreaded or the static-multithreaded library. Which means
that whoever builds the DLL must be aware of the application settings,
and set the DLL build flags accordingly. There are even more problems
when running an app and a DLL built by different vendors' compilers,
e.g. Microsoft C vs. Borland C.

Another cause for trouble is WINAPI. Not even Microsoft is using WINAPI
in their C RTL, but only in "pure" Win32 functions. Please, please
change it to CDECL! Otherwise, whoever wants to write *portable*
programs that use zlib, has to decorate all the callbacks using ZEXPORT,
and unixers surely won't like this.

There are even more sources of problems, but I wish to stop, and I will
continue arguing on this only if necessary :)

**

So here is my solution. In short, I fixed the problem of differentiating
between when to use dllexport and dllimport, I changed myself STDCALL to
CDECL, I fixed some problems that allowed two different definitions for
ZEXPORT under Borland C (obviously triggering warnings), I put the
inclusion of <windows.h> in a proper place, and I made the library
compilable under Microsoft C when ZLIB_DLL is set. Oh, and I removed the
default ZLIB_DLL: it is set explicitly in win32/makefile-dll.msc
but as I said, any Win32 compiler can build the DLL just fine even
without it, since there is zlib.def.

1. dllexport and dllimport must be used properly. The solution so far,
   with ZLIB_DLL, is not enough. In libpng, for example, there are
   separate PNG_BUILD_DLL and PNG_USE_DLL, but here I have a solution
   that spares the poor ZLIB.DLL user of knowing two extra names.
   Here it is:
   Define a ZLIB_INTERNAL in every zlib source file, right before
   including any zlib header. This will allow the following test to
   select the right __declspec attribute.

/* ... under an #ifdef ZLIB_DLL guard ... */
#        ifdef ZLIB_INTERNAL
#          define ZEXPORT  CDECL __declspec(dllexport)
#          define ZEXPORTVA  CDECL __declspec(dllexport)
#        else
#          define ZEXPORT  CDECL __declspec(dllimport)
#          define ZEXPORTVA  CDECL __declspec(dllimport)
#        endif


2. No matter how hard C programmers try to be high-level, from time to
   time they have to remember that C is in fact some ASM++, and it's not
   "int* ptr_a, ptr_b, ptr_c", but it is "int *ptr_a, *ptr_b, *ptr_c".
   And it's not
     ZEXTERN const char * ZEXPORT zlibVersion OF((void))
   but it's
     ZEXTERN const char ZEXPORT * zlibVersion OF((void))

   Borland C accepts both constructs, but Microsoft C (at least my
   version, supplied with MS Visual C++ 6.0) accepts only the second.

Here is the patch applied to zconf.h, but you must also consider the
definition of ZLIB_INTERNAL. So you can download everything as a whole
from

  http://www.cs.toronto.edu/~cosmin/pngtech/z_rle/zlib-1.2.0.1-cos.zip

or the entire patch from

  http://www.cs.toronto.edu/~cosmin/pngtech/z_rle/zlib-1.2.0.1-cos.diff

There are other changes in this update, and I will describe them in a
separate email.

Best regards,
Cosmin

**

@@ -172,46 +164,43 @@
 #  endif
 #endif

-#if defined(WIN32) && (!defined(ZLIB_WIN32_NODLL)) && (!defined(ZLIB_DLL))
-#  define ZLIB_DLL
-#endif
-
-/* Compile with -DZLIB_DLL for Windows DLL support */
-#if defined(ZLIB_DLL)
+/* If building or using a Windows DLL, compile with -DZLIB_USE_DLL.
+ * The calls to ZEXTERN functions will be more efficient this way.
+ */
+#ifdef ZLIB_DLL
 #  if defined(_WINDOWS) || defined(WINDOWS) || defined(WIN32)
+#    include <windows.h>
 #    ifndef WINAPIV
 #      ifdef FAR
 #        undef FAR
 #      endif
-#      include <windows.h>
 #    endif
 #    ifdef WIN32
-#      define ZEXPORT  WINAPI
-#      define ZEXPORTVA  WINAPIV
+#      if !(defined(__BORLANDC__) && (__BORLANDC__ < 0x500))
+#        ifdef ZLIB_INTERNAL
+#          define ZEXPORT  CDECL __declspec(dllexport)
+#          define ZEXPORTVA  CDECL __declspec(dllexport)
+#        else
+#          define ZEXPORT  CDECL __declspec(dllimport)
+#          define ZEXPORTVA  CDECL __declspec(dllimport)
+#        endif
+#      endif
 #    else
 #      define ZEXPORT  WINAPI _export
 #      define ZEXPORTVA  FAR _cdecl _export
 #    endif
 #  endif
-#  if defined (__BORLANDC__)
-#    if (__BORLANDC__ >= 0x0500) && defined (WIN32)
-#      include <windows.h>
-#      define ZEXPORT __declspec(dllexport) WINAPI
-#      define ZEXPORTVA __declspec(dllexport) WINAPIV
-#    else
-#      if defined (_Windows) && defined (__DLL__)
-#        define ZEXPORT _export
-#        define ZEXPORTVA _export
-#      endif
-#    endif
-#  endif
 #endif

 #if defined (__BEOS__)
-#  if defined (ZLIB_DLL)
-#    define ZEXTERN extern __declspec(dllexport)
-#  else
-#    define ZEXTERN extern __declspec(dllimport)
+#  ifdef ZLIB_DLL
+#    ifdef ZLIB_INTERNAL
+#      define ZEXPORT __declspec(dllexport)
+#      define ZEXPORTVA __declspec(dllexport)
+#    else
+#      define ZEXPORT __declspec(dllimport)
+#      define ZEXPORTVA __declspec(dllimport)
+#    endif
 #  endif
 #endif





More information about the Zlib-devel mailing list