• VC++编译libpng


    1简介    1

    2 Visual C++6.0    2

    2.1 打开项目    2

    2.2 编译宏    3

    2.2.1 小结    5

    3 Visual C++2010    6

    3.1 打开项目    6

    3.2 编译宏    6

    3.2.1 PNG_USE_DLL    6

    3.2.2 Z_SOLO    7

    3.3 自定义编译    8

    3.4 自定义环境变量    8

    3.4.1 定义    9

    3.4.2 使用    9

    1简介

    libpng是一个读写 .png 文件的 C 函数库,其下载网址如下:

    http://sourceforge.net/projects/libpng/files

    本文对libpng自带的Visual C++项目进行剖析。

    2 Visual C++6.0

    2.1 打开项目

    版本1.0.63至版本1.4.16libpng带有Visual C++6.0的项目。本章以版本1.4.12进行说明。假定其存放目录为V:libpngv1.4.12,如下图所示:

    VC++6.0的工作区文件位于V:libpngv1.4.12projectsvisualc6libpng.dsw。首先使用记事本打开这个文件,其内容节选如下:

    也就是说libpng.dsw包含了项目zlib.dsp,后者的存放路径为V:libpngv1.4.12projectsvisualc6......zlibprojectsvisualc6zlib.dsp,即V:libpngzlibprojectsvisualc6zlib.dsp

    zlib也是一个开源的C函数库,其版本1.2.21.2.31.2.4带有Visual C++6.0的项目。这里,把版本1.2.3zlib复制到V:libpngzlib,其目录结构如下图所示:

    现在,可以使用VC++6.0打开V:libpngv1.4.12projectsvisualc6libpng.dsw了。

    2.2 编译宏

    项目libpng5个配置项,如下图所示:

    "Win32 DLL Release"生成Release版的动态库;

    "Win32 DLL Debug"生成Debug版的动态库,用于调试程序;

    "Win32 DLL VB"生成供非C语言(如:VB6.0)调用的动态库;

    "Win32 LIB Release"生成Release版的静态库;

    "Win32 LIB Debug"生成Debug版的静态库,用于调试程序。

    "Win32 DLL Release"和"Win32 DLL Debug"定义了宏PNG_BUILD_DLL

    "Win32 DLL VB"定义了宏PNG_BUILD_DLL,PNGAPI=__stdcall,PNG_NO_MODULEDEF

    "Win32 LIB Release"和"Win32 LIB Debug"没有定义特殊的宏。

    这些宏都有什么含义呢?

    先看看libpng的一个接口函数定义:

    PNG_EXPORT(void,png_set_expand) PNGARG((png_structp png_ptr));

    PNG_EXPORT有两份定义,最终形式是一致的即:

    #define PNG_EXPORT(type,symbol) PNG_IMPEXP type PNGAPI symbol

    展开宏PNG_EXPORTPNGARG,函数png_set_expand的声明如下:

    PNG_IMPEXP void PNGAPI png_set_expand(png_structp png_ptr);

    PNGAPI默认为 __cdecl,"Win32 DLL VB"配置项里强制规定它为__stdcall。因为VB6.0只能调用__stdcall的函数。

    接下来的关键是PNG_IMPEXP,它有三份定义:

    //1份定义("Win32 DLL Release"和"Win32 DLL Debug")

    #if !defined(PNG_IMPEXP) && defined(PNG_BUILD_DLL) && !defined(PNG_NO_MODULEDEF)

    # define PNG_IMPEXP

    #endif

     

    //2份定义("Win32 LIB Release"和"Win32 LIB Debug")

    # if !defined(PNG_IMPEXP) && (!defined(PNG_DLL) ||

    0 /* WINCOMPILER_WITH_NO_SUPPORT_FOR_DECLIMPEXP */)

    # define PNG_IMPEXP

    # endif

     

    //3份定义"Win32 DLL VB"

    # ifndef PNG_IMPEXP

    # ifdef PNG_BUILD_DLL

    # define PNG_IMPEXP __declspec(dllexport)

    # else

    # define PNG_IMPEXP __declspec(dllimport)

    # endif

    # endif

    也就是说:选中配置"Win32 DLL VB"函数png_set_expand的声明如下:

    __declspec(dllexport) void __stdcall png_set_expand(png_structp png_ptr);

    否则函数png_set_expand的声明如下:

    void __cdecl png_set_expand(png_structp png_ptr);

    项目pngtest的"Win32 DLL Release"和"Win32 DLL Debug"用到了libpng的动态库,它们都定义了宏PNG_DLL。此时函数png_set_expand的声明如下:

    __declspec(dllimport) void __cdecl png_set_expand(png_structp png_ptr);

    2.2.1 小结

    1PNGAPI规定了导出函数的调用约定,默认为__cdecl,可强制改为__stdcall

    2、编译生成libpng动态库时,请定义宏PNG_BUILD_DLL

    3、如果使用.def文件,请不要定义宏PNG_NO_MODULEDEF,导出函数前没有__declspec(dllexport),编译器通过.def文件自动导出函数;pngwin.def文件在"Win32 DLL VB"下是被排除编译的,如下图所示。因为没有使用.def文件,因此需要定义宏PNG_NO_MODULEDEF,给导出函数增加__declspec(dllexport)修饰符;

    4、客户端程序要使用libpng动态库,请定义宏PNG_DLL,它会给导出函数前增加__declspec(dllimport)修饰符。

    3 Visual C++2010

    3.1 打开项目

    版本1.4.12至版本1.6.18libpng带有Visual C++2010的项目。本章以版本1.6.18进行说明。假定其存放目录为V:libpngv1.6.18,如下图所示:

    使用vc2010打开V:libpngv1.6.18projectsvstudiovstudio.sln

    3.2 编译宏

    3.2.1 PNG_USE_DLL

    libpng没有定义什么特殊的宏。客户端程序pngstestpngunknownpngvalid在使用libpng动态库时,定义了宏PNG_USE_DLL

    现在简单了,只要记住宏PNG_USE_DLL即可。问题是:libpng是如何简化这个问题的?

    首先看pngpriv.h,这是libpng内部使用的头文件。

    #ifndef PNG_BUILD_DLL

    #ifdef DLL_EXPORT

    #else

    #ifdef _WINDLL

    #define PNG_BUILD_DLL

    #else

    #endif

    #endif

    #endif

     

    #ifndef PNG_IMPEXP

    #ifdef PNG_BUILD_DLL

    #define PNG_IMPEXP PNG_DLL_EXPORT

    #else

    #define PNG_IMPEXP

    #endif

    #endif

    当编译生成libpng动态库时,宏_WINDLL被定义。上面的代码将定义PNG_BUILD_DLL,并定义PNG_IMPEXPPNG_DLL_EXPORT,即__declspec(dllexport)

    当编译生成libpng静态库时,宏PNG_BUILD_DLL不会被定义,因此PNG_IMPEXP会被定义为空。

    这里有必要说明一下宏_WINDLL,在VC++6.0里它的含义是:是否使用MFC共享库,使用了就会定义它,未使用就不会定义它。所以,这里用_WINDLL是不兼容VC++6.0的,为了兼容VC++6.0应该把_WINDLL更改为_USERDLL

    再来看看客户端程序,它会包含png.h,后者会包含pngconf.h。下面的代码节选自pngconf.h

    #ifndef PNG_IMPEXP

    # if defined(PNG_USE_DLL) && defined(PNG_DLL_IMPORT)

    /* This forces use of a DLL, disallowing static linking */

    # define PNG_IMPEXP PNG_DLL_IMPORT

    # endif

     

    # ifndef PNG_IMPEXP

    # define PNG_IMPEXP

    # endif

    #endif

    很简单:定义PNG_USE_DLL时,PNG_IMPEXPPNG_DLL_IMPORT__declspec(dllimport);未定义PNG_USE_DLL时,PNG_IMPEXP为空。

    3.2.2 Z_SOLO

    编译zlib时用到了宏Z_SOLO。它的含义是对zlib进行裁剪。zlib被裁剪后,以下函数不会被实现:

    compress,compress2,compressBound,gzFile,gz_error,gz_intmax,gz_strwinerror,gzbuffer,gzclearerr,gzclose,gzclose_r,gzclose_w,gzdirect,gzdopen,gzeof,gzerror,gzflush,gzgetc,gzgetc_,gzgets,gzoffset,gzoffset64,gzopen,gzopen64,gzopen_w,gzprintf,gzputc,gzputs,gzread,gzrewind,gzseek,gzseek64,gzsetparams,gztell,gztell64,gzungetc,gzvprintf,gzwrite,uncompress,zcalloc,zcfree

    简而言之就是libpng用不了那么多的zlib函数,编译时对zlib进行了裁剪。

    3.3 自定义编译

    libpng依赖于pnglibconfpnglibconf没有任何文件,编译时它做了什么?

    它其实就做了一件事儿——复制文件。如下图所示:

    编译pnglibconf时将执行自定义编译。上图里就是执行如下命令

    copy ......scriptspnglibconf.h.prebuilt ......pnglibconf.h

    上面的相对路径是相对于项目文件V:libpngv1.6.18projectsvstudiopnglibconfpnglibconf.vcxproj的,所以其实就是把V:libpngv1.6.18scriptspnglibconf.h.prebuilt复制到V:libpngv1.6.18pnglibconf.h

    3.4 自定义环境变量

    选中zlib项目的任一文件,可以查看它的属性。如下图所示:

    上图的ZLibSrcDir就是一个环境变量,它指明了zlib源代码所在的目录。

    3.4.1 定义

    ZLibSrcDir的定义在文件V:libpngv1.6.18projectsvstudiozlib.props里,如下图所示:

    上图将设置环境变量ZLibSrcDir........zlib-1.2.8

    3.4.2 使用

    需要使用环境变量ZLibSrcDir的项目,请在相应的.vcxproj文件里插入一行语句,如下图所示:

    ZLibSrcDir是一个相对路径,它是相对于各个vc项目文件的(*.vcxproj)。以libpng.vcxproj为例,该文件位于V:libpngv1.6.18projectsvstudiolibpng,因此ZLibSrcDir指向的绝对路径就是V:libpngv1.6.18projectsvstudiolibpng........zlib-1.2.8,即V:libpngzlib-1.2.8。也就是说需要把zlib-1.2.8的文件都复制到V:libpngzlib-1.2.8目录,或者修改环境变量ZLibSrcDir

    使用环境变量ZLibSrcDir指向zlib源代码的位置,这是个非常好的功能。

  • 相关阅读:
    排序算法之冒泡排序
    hadoop程序启动
    开播小记
    3.3面向对象封装案例1摆家具
    3.2面向对象基础语法
    3.1类和对象
    2.12函数进阶
    2.11变量的引用_可变不可变类型_局部变量和全局变量
    2.10第二章综合应用_名片管理系统
    2.8函数基础
  • 原文地址:https://www.cnblogs.com/hanford/p/6168813.html
Copyright © 2020-2023  润新知