如何构建 libjpeg 9b 的 DLL 版本?

How to build a DLL version of libjpeg 9b?

我想构建 libjpeg 9b 的 DLL 版本。根据文档here看来,除了将Configuration Type设置为[=外,还需要在每个要导出的函数声明前添加预处理器__declspec(dllexport)__declspec(dllimport) 18=]。但这不是一件容易的事,因为 libjpeg 中的函数太多了。那么,是否有任何捷径或变通方法可以在不对 jpeglib.h 进行或只进行少量修改的情况下构建 DLL libjpeg?是否有可用的 libjpeg 9b 的任何 DLL 就绪源?我在 Windows 7 64 位上使用 Visual Studio 2015。谢谢你的回答。

PS:我从http://www.ijg.org/files/下载了libjpeg 9b的源码。这是官方下载地址吗?我问是因为 .vcxproj(最初是 .v10)文件的开头字节似乎无效(C2 8B C2 AF C2 A8)所以 Visual Studio 无法打开它。

已在 [GitHub]: CristiFati/Prebuilt-Binaries - (master) Prebuilt-Binaries/LibJPEG.

上发布构建(静态/动态)



像现在几乎所有的软件一样,libjpeg 也托管在 [GitHub]: winlibs/libjpeg - libjpeg-9b 上。我从两个地方都下载了它,进行了比较,只发现了一些细微的差别(其中 none 在源代码中)弹出。我将在 GitHub 版本上进行解释。不幸的是,没有这方面的演练,所以我不得不查看一些文件以弄清楚必须做什么。以下是步骤列表:

1。准备地面

1st 东西是解压压缩的(zip / tar.gz) 将文件内容放入文件夹(并在那里打开 cmd 控制台)。该文件夹包含一堆文件。我们需要的第一个stmakefile.vc。顾名思义,它是一个 Makefile,由一系列通常用于构建内容的 rules/instructions 组成。

顺便说一下,我使用的是 VStudio(社区)2015 (14.0 ) 用于此任务(但新版本应该没有差异)。

处理Makefiles的工具是nmake([MS.Docs]: NMAKE reference)。我们需要针对该文件调用它。 nmake 位于“%VSTUDIO_INSTALL_DIR%\VC\bin\nmake.exe”(环境变量并不存在,它只是一个路径占位符);通常是“%SystemDrive%\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin\nmake.exe”(例如在我的机器上它是 "C:\Install\x86\Microsoft\Visual Studio Community15\VC\bin\nmake.exe").

请注意,在处理 VStudio 命令行工具时,最好是:

  • 使用 vcvarsall(这是一个 (batch) 工具,可以设置一些环境变量,例如%PATH%, %INCLUDE%, %LIB%, ...), 所以所有VStudio 工具在没有完整路径的情况下可用。但由于它也位于“%VSTUDIO_INSTALL_DIR%\VC\vcvarsall.bat”,因此不值得 locate/call it
  • 开始菜单使用VS2015工具命令提示符(基本上调用vcvarsall
  • [MS.Docs]: Building on the Command Line 包含有关此主题的更多详细信息

现在我们知道 nmake 的位置,让我们 运行:

"%VSTUDIO_INSTALL_DIR%\VC\bin\nmake.exe" /f makefile.vc setup-v10

(不要忘记将nmake的路径包含在dblquotes("中), 特别是如果它包含 SPACEs).

如果运行遇到问题,Google可能会产生解决方案:

setup-v10 是一个 Makefile 目标,它只是重命名文件夹中的一些文件(坦白说,我不知道为什么文件不像在 1st 位置重命名的那样)。

运行在文件夹中执行命令后,应该有2个VStudio解决方案文件:

  • jpeg.sln - 其中包含一个项目:
    • jpeg.vcxproj - 这是负责构建 lib
    • 的项目
  • apps.sln - 其中包含一堆项目(我不 know/care 他们做什么):
    • djpeg.vcxproj - 这是我唯一要提到的,因为我将用它来测试构建的库

2。构建 jpeg

第 1st 要注意的是,上一节中生成的 solution/project 文件适用于 VStudio 2010。但这不是问题,因为 VStudio 2015 能够处理它们(加载它们时,它会进行所有必要的转换以使它们保持最新)。

打开 jpeg.sln,将揭示有关解决方案(和项目)的一些(不愉快的)内容:

  • 只有Win32(32位或x86)平台
    • 只有发布配置
  • 正如您已经提到的,它构建了一个静态库

无论如何,解决方案应该构建 OOTB。完成后,您会注意到一个 Release 文件夹,其中应该包含(除了一堆中间文件 - .obj 文件),一个 4+ MB jpeg.lib 文件是静态库。知道代码(和项目相关文件)都OK了,我们继续下一步。

2.1 构建 jpeg DLL

为了避免破坏现有的功能,我们应该创建一个新的配置(注意创建新的平台的过程您的项目(几乎)相同):

  • 从菜单中选择 构建 -> 配置管理器...
  • 在对话框中弹出,向上单击 Release 组合框和 select
  • New Solution Configuration对话框中,select新配置的名称:我选择了Release-DLL(从现在开始我要依赖这个名字)
  • 确保在组合框
  • 复制设置select发布
  • 勾选新建项目配置

按下OK后,新的Release-DLL配置将与Release[=]相同415=]。下一步是对其进行必要的更改,以实现我们的目标。在 Solution Explorer 中的 jpeg 项目上 RClick(在 的左侧VStudio window), 然后选择 Properties:

在上图中,有 jpeg 项目设置 window,显示了它们最后的样子。我突出显示(使用颜色)不同的兴趣点:

  • 蓝色:平台/配置对:

    • 正在修改(在最上面的对话框中)
    • Active(在VStudio主window后面)

    修改某些平台 / 配置设置时确保它是活动的 (蓝色矩形中的数据是相同的),否则你会用头撞墙并浪费时间试图弄清楚为什么看起来正确的东西不能按预期工作。在我看来,弹出此对话框时,它应该具有 active 值,但情况并非总是如此。

  • 红色:应该修改(或至少需要注意)的项目:
    • 配置类型显然应该是动态库(.dll)
    • Platform Toolset 应该是 Visual Studio 2015(我提到这个,因为它碰巧打开了一个 VStudio 2010 项目与 VStudio2015,它保留了旧的工具集,并继续使用它进行构建,但前提是你同时安装了两个版本)
  • 绿色:建议修改的项目。这些只是文件夹。请注意 $(Platform) 变量(我将其用作一个好习惯),它在构建多个平台时会派上用场(例如 Win32x64)

全部保存并构建。构建成功后,会出现一个新的文件夹Win32-Release-DLL,和之前的一样,里面会有一堆文件plus jpeg.dll。人们可能认为它已经完成了,但事实并非如此。 .dll里面的所有代码都是compiled/built,但是没有导出,所以.dll 几乎无法使用。您可以检查许多 .dll(或 .exe)属性,使用 Dependency Walker. You can look at the screenshots from 打开它 - 在我们的例子中,导出区域将是空.

最后一点:如果您认为将来需要为其他平台构建(x64,甚至ARM),同时你还需要做一些调试(添加一个Debug配置),添加DebugWin32 平台下配置 首先 ,然后 然后 从 [=133 创建新平台=]Win32,否则您需要为每个创建的平台添加 Debug 配置,然后再将 Debug 配置添加到 Win32.

2.2 从DLL

导出数据

请注意:除了 __declspec(dllexport) 方法外,还有 2 个(处理时从 Win .dlls 导出:

但是,由于我们不知道代码并且可能有很多符号要导出,所以这 3 个中的任何一个都不可扩展(它们可能需要很多 research/work)。不管怎样,我们会坚持原来的做法:

  1. 保存下面这段代码:

    #pragma once
    
    #if defined(_WIN32)
    #  if defined(LIBJPEG_STATIC)
    #    define LIBJPEG_EXPORT_API
    #  else
    #    if defined(LIBJPEG_EXPORTS)
    #      define LIBJPEG_EXPORT_API __declspec(dllexport)
    #    else
    #      define LIBJPEG_EXPORT_API __declspec(dllimport)
    #    endif
    #  endif
    #else
    #  define LIBJPEG_EXPORT_API
    #endif
    

    jexport.h 的文件中,在 libjpeg 源文件夹中。这是一个非常标准的 header 文件,用于处理 .dll exports.
    接下来,将其添加到项目中:在 Solution ExplorerRClick on Header Files -> Add -> Existing Item.. .

  2. 利用新文件

    --- jmorecfg.h.orig 2016-03-30 09:38:56.000000000 +0300
    +++ jmorecfg.h  2017-06-09 21:04:33.762535400 +0300
    @@ -30,6 +30,8 @@
      * in all cases (see below).
      */
    
    +#include "jexport.h"
    +
     #define BITS_IN_JSAMPLE  8 /* use 8, 9, 10, 11, or 12 */
    
    
    @@ -245,7 +247,8 @@
     /* a function referenced thru EXTERNs: */
     #define GLOBAL(type)       type
     /* a reference to a GLOBAL function: */
    -#define EXTERN(type)       extern type
    +
    +#define EXTERN(type)       extern LIBJPEG_EXPORT_API type
    
    
     /* This macro is used to declare a "method", that is, a function pointer.
    

    以上是一个差异。请参阅 修补 ut运行ner 部分)如何在 Win 上应用补丁(基本上,以 一个“+” 符号开头的每一行,以及以 [= 开头的每一行308=]一个“-” 符号熄灭)。但是,由于更改微不足道,因此也可以手动完成。需要更改的文件是 jmorecfg.h(需要两件事):

    • 在开头包含新文件 (#include "jexport.h")
    • 修改第251行(将#define EXTERN(type) extern type替换为#define EXTERN(type) extern LIBJPEG_EXPORT_API type

    我认为此步骤是某种解决方法 (gainarie),但正如我所说,"real thing" 需要太多的工作(和时间)。

  3. 告诉编译器考虑我们的更改

    编辑项目设置(再次注意Platform / Configuration),select Configuration Properties -> C/C++ -> Preprocessor -> Preprocessor Definitions 并替换旧值(在我的例子中:WIN32;NDEBUG;_LIB;_CRT_SECURE_NO_WARNINGS) 到 WIN32;LIBJPEG_EXPORTS;_CRT_SECURE_NO_WARNINGS;NDEBUG。我所做的是:

    1. 删除 _LIB
    2. 添加LIBJPEG_EXPORTS
    3. 有些变化

    [MS.Docs]: /D (Preprocessor Definitions) 可能包含一些有用的信息。

    作为旁注,经过上述更改后,原始(或"normal")行为(发布配置)不会 OK (它会生成一堆警告,但从技术上讲这是不正确的)。那是因为我不想依赖 _LIB 宏来区分静态/动态库构建。为了解决问题,预处理器定义中添加LIBJPEG_STATIC for Release[=415] =]配置(按照与上面相同的步骤)。

全部保存并构建。构建成功后,jpeg.dll被覆盖,更重要的是:一个新文件jpeg.lib 将被创建;这告诉我们 jpeg.dll 输出了一些东西。您可以使用 Dependency Walker.

再次检查

3。测试 DLL

  • 这是可选的,我这样做是为了确保我到目前为止所做的一切没有白费
  • 通过测试,我仅指构建和 运行ning,这意味着我没有进行任何 功能测试(从 .dll 实际上做他们应该做的事)

加载 apps.sln 解决方案,最好是在新的 VStudio 实例中。正如我所说,我只关心 djpeg 项目。

  1. 1st 要做的事情,就是为现有的 Release 配置构建它。但是,由于对 jpeg 库所做的更改,它不会构建 OOTB(会有 linker 错误)。为了摆脱它们,编辑其设置,Preprocessor Definitions(就像上一步一样),并添加 LIBJPEG_STATIC(不要忘记分隔符 (;)).

    构建应该成功,在djpeg\Release文件夹下,应该有一个djpeg.exe文件。尝试 运行 它会成功(这是我唯一关心的事情)。

  2. 构建一个使用我们的 .dll:

    的新可执行文件
    • 就像 jpeg 库的情况一样,创建一个新配置:Release-DLL(确保执行所有步骤, 但不要改变它)
    • 只需要一个改变:让链接器知道我们在哪里构建我们的.lib文件。转到项目设置,Configuration Properties -> Linker -> Input -> Additional Dependencies:第 1stRelease\jpeg.lib.很明显,路径不对,所以我们需要把Release替换成Win32-Release-DLL(当然你可以用VStudio 宏(针对 平台 / 配置)。可能会检查 [MS.Docs]: .Lib Files as Linker Input.

全部保存并构建。构建成功后,在djpeg\Release-DLL下应该有一个djpeg.exe文件。尝试 运行 它将 失败 ,因为它找不到 jpeg.dll。通过将 jpeg.dll 复制到(检查 [MS.Docs]: Dynamic-Link Library Search Order 的语义)来修复该问题:

  • djpeg.exe的文件夹
  • %PATH% 环境变量中的其中一个文件夹(或者反过来,附加 jpeg.dll 文件夹到 %PATH%)

同样,您可以使用 Dependency Walker 检查 2 个可执行文件(但大小差异足以说明:2nddjpeg.exe明显小了),看哪个取决于jpeg.dll。不管怎样,这是我电脑上的输出(是的,Dependency Walker 也可以充当命令行 :)):

e:\Work\Dev\Whosebug\q044450813\src\libjpeg-libjpeg-9b>"c:\Install\x86\Depends\Dependency Walker-politist-texan\AllVers\depends.exe" /c /ot:static.txt djpeg\Release\djpeg.exe

e:\Work\Dev\Whosebug\q044450813\src\libjpeg-libjpeg-9b>"c:\Install\x86\Depends\Dependency Walker-politist-texan\AllVers\depends.exe" /c /ot:dynamic.txt djpeg\Release-DLL\djpeg.exe

e:\Work\Dev\Whosebug\q044450813\src\libjpeg-libjpeg-9b>type static.txt | findstr -i "jpeg.dll"

e:\Work\Dev\Whosebug\q044450813\src\libjpeg-libjpeg-9b>type dynamic.txt | findstr -i "jpeg.dll"
     [   ] e:\work\dev\Whosebug\q044450813\src\libjpeg-libjpeg-9b\djpeg\release-dll\JPEG.DLL
[   ]  e:\work\dev\Whosebug\q044450813\src\libjpeg-libjpeg-9b\djpeg\release-dll\JPEG.DLL   2017-06-09 21:16  2017-06-09 21:16    237,056  A      0x00000000     0x0003ECC8     x86  GUI        CV,Unknown  0x10000000      Unknown      0x0003E000    Not Loaded  N/A              N/A              0.0        14.0        6.0     6.0



更新#0

我还: