Laurent
Laurent

Reputation: 68

Some syntax I don't know in zlib (C/C++) ZEXTERN ZEXPORT OF ... compile error

I am trying to compile zlib 1.2.11 to replace an old version we use with vxWorks 6.8, and I run into compile issues.

Checking the code, I don't know the syntax which has been used there:

ZEXTERN int ZEXPORT gzwrite OF((gzFile file, voidpc buf, unsigned len));

What's ZEXTERN, ZEXPORT, and OF()?

Also:

int ZEXPORT gzgetc(file)
    gzFile file;
{
    unsigned char c;
    return gzread(file, &c, 1) == 1 ? c : -1;
}

It looks like an hybrid between C and C++.

I couldn't fine much documentation.

Upvotes: 1

Views: 728

Answers (1)

Remy Lebeau
Remy Lebeau

Reputation: 596307

ZEXTERN, ZEXPORT, and OF() are preprocessor macros defined in zlib's zconf.h header file:

#if defined(WINDOWS) || defined(WIN32)
   /* If building or using zlib as a DLL, define ZLIB_DLL.
    * This is not mandatory, but it offers a little performance increase.
    */
#  ifdef ZLIB_DLL
#    if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500))
#      ifdef ZLIB_INTERNAL
#        define ZEXTERN extern __declspec(dllexport)
#      else
#        define ZEXTERN extern __declspec(dllimport)
#      endif
#    endif
#  endif  /* ZLIB_DLL */
   /* If building or using zlib with the WINAPI/WINAPIV calling convention,
    * define ZLIB_WINAPI.
    * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI.
    */
#  ifdef ZLIB_WINAPI
#    ifdef FAR
#      undef FAR
#    endif
#    include <windows.h>
     /* No need for _export, use ZLIB.DEF instead. */
     /* For complete Windows compatibility, use WINAPI, not __stdcall. */
#    define ZEXPORT WINAPI
#    ifdef WIN32
#      define ZEXPORTVA WINAPIV
#    else
#      define ZEXPORTVA FAR CDECL
#    endif
#  endif
#endif

#if defined (__BEOS__)
#  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

#ifndef ZEXTERN
#  define ZEXTERN extern
#endif
#ifndef ZEXPORT
#  define ZEXPORT
#endif
#ifndef ZEXPORTVA
#  define ZEXPORTVA
#endif

...

#ifndef OF /* function prototypes */
#  ifdef STDC
#    define OF(args)  args
#  else
#    define OF(args)  ()
#  endif
#endif

In a nutshell:

When zlib is compiled/linked-to as a DLL, ZEXTERN maps to extern __declspec(dllexport) or extern __declspec(dllimport) on Windows, and to __declspec(dllexport) or __declspec(dllimport) on BEOS. For all other build configurations, it maps to extern instead.

ZEXPORT maps to WINAPI (aka __stdcall) on Windows, otherwise it maps to nothing (ie, the compiler's default calling convention, which is usually __cdecl).

OF() emits the specified parameter list under standard C/C++, otherwise it hides the list.

So, for example, when compiling zlib as a DLL for Windows, this declaration:

ZEXTERN int ZEXPORT gzwrite OF((gzFile file, voidpc buf, unsigned len));

is seen by the compiler as this code:

extern __declspec(dllexport) int __stdcall gzwrite (gzFile file, voidpc buf, unsigned len);

Under certain compilers, it could end up being as simple as this instead:

extern int gzwrite ();

Upvotes: 4

Related Questions