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

use*_*911 2 dll dllimport libjpeg dllexport visual-studio-2015

我想构建libjpeg 9b的DLL版本.根据这里的文档, 除了将配置类型设置为"动态库(.dll)"之外,似乎我们需要添加预处理器__declspec(dllexport)__declspec(dllimport)在声明要导出的每个函数之前.但这不是一件容易的事,因为libjpeg中有很多功能.那么,是否有任何捷径或解决方法来构建DLL libjpeg没有或几乎没有修改jpeglib.h?是否有任何DLL-ready libjpeg 9b可用?我在Windows 7 64bit上使用Visual Studio 2015.感谢您的回答.

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

Cri*_*ati 6

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

1.准备好地面

1 的事情是提取压缩(ZIP/tar.gz的)文件内容放到一个文件夹(并有CMD打开后里面有控制台).该文件夹包含一堆文件.在1 一个,我们需要的是makefile.vc.顾名思义,它是一个Makefile,由一系列用于构建内容的规则/指令组成.

处理Makefile的工具是nmake([MS.Docs]:NMAKE参考).我们需要针对该文件调用它.nmake位于" %VSTUDIO_INSTALL_DIR%\ VC\bin \nmake.exe "中(env var实际上并不存在,它只是一个路径占位符); 通常是" %SystemDrive%\ Program Files(x86)\ Microsoft Visual Studio 14.0\VC\bin \nmake.exe"(例如在我的机器上它是"C:\ Install\x86\Microsoft\Visual Studio Community\2015\VC"\bin \nmake.exe ").

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

  • 使用vcvarsall(这是一个(批处理)工具,设置一些环境变量,如%PATH%,%INCLUDE%,%LIB%,...),因此所有VStudio工具都可以在没有完整路径的情况下使用.但由于它也位于" %VSTUDIO_INSTALL_DIR%\ VC\vcvarsall.bat "中,因此找到/调用它并不值得
  • 开始菜单使用VS2015工具命令提示符(基本上调用vcvarsall)
  • [MS.Docs]:在命令行上构建包含有关此主题的更多详细信息

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

"%VSTUDIO_INSTALL_DIR%\VC\bin\nmake.exe" /f makefile.vc setup-v10
Run Code Online (Sandbox Code Playgroud)

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

设置-V10是一个Makefile的目标,它只是一些重命名的文件夹(坦白地说,我不知道为什么这些文件并不像已经在1米更名为ST的地方).

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

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

2.构建jpeg库

在1 的事情要注意的是,在上一节中所产生的解决方案/项目文件是2010 VStudio.但这不是问题,因为VStudio 2015能够处理它们(当加载它们时,它将进行所有必要的转换以使它们更新).

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

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

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

2.1构建jpeg DLL

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

  • 从菜单中选择Build - > Configuration Manager ...
  • 在弹出的对话框中,单击Release组合框并选择<New ...>
  • 在" 新建解决方案配置"对话框中,选择新配置的名称:我选择了Release-DLL(从现在开始,我将依赖此名称)
  • 确保组合框中复制设置中选择" 释放 "
  • 选中" 创建新项目配置"

OK后,新的Release-DLL配置将与Release相同.下一步是对其进行必要的更改,以实现我们的目标.R单击解决方案资源管理器中jpeg项目(在VStudio窗口的左侧),然后选择" 属性":

VStudio设置

在上图中,有jpeg项目设置窗口,显示它们最后应该是什么样子.我突出(使用颜色)不同的兴趣点:

  • 蓝色:平台/配置对:

    • 正在修改(在最顶层的对话框中)
    • 活动(在后面的VStudio主窗口中)

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

  • 红色:修改的项目(或至少需要注意):
    • 配置类型显然应该是动态库(.dll)
    • 平台工具集应该是Visual Studio 2015(我提到这一点,因为碰巧用VStudio2015打开了一个VStudio 2010项目,它保留了旧的工具集,并继续用它构建,但这只是在你安装了两个版本的情况下)
  • 绿色:建议修改的项目.这些只是文件夹.注意fatal error U1052: file 'win32.mak' not found变量(我用作一个好习惯),在构建多个平台(例如Win32x64)时派上用场

全部保存并构建.构建成功后,将出现一个新文件夹Win32-Release-DLL,与前一个文件夹一样,它将包含一堆文件 jpeg.dll.人们可能会认为它已经完成了,但事实并非如此.所有代码都是在.dll中编译/构建的,但是它没有被导出,所以.dll几乎无法使用.您可以检查许多使用Dependency Walker打开它的.dll(或.exe)属性.您可以查看[SO]的屏幕截图:Excel VBA,无法从DLL文件中找到DLL入口点(@ CristiFati的答案) - 在我们的示例中,导出区域将为空.

最后要注意的是:如果您认为将来需要为其他平台(x64,甚至是ARM)构建,并且还需要进行一些调试(添加调试配置),请在下面添加Debug配置首先是Win32平台,然后Win32创建新平台,否则在将调试配置添加到Win32之前,您需要为每个创建的平台添加Debug配置.

2.2从DLL导出数据

就像一个注释:除了$(Platform)方法之外,还有2个(当处理Win .dll的导出时):

但是,由于我们不知道代码并且可能有许多符号要导出,因此3中的任何一个都不可扩展(它们可能需要大量的研究/工作).无论如何,我们将坚持原来的方法:

  1. 保存以下代码:

    #pragma once
    
    #if defined(_WIN32)
    #  if defined(LIBJPEG_STATIC) || defined(_LIB) || defined(JPEG_STATIC)
    #    define LIBJPEG_EXPORT_API
    #  else
    #    if defined(LIBJPEG_EXPORTS) || defined(JPEG_EXPORTS)
    #      define LIBJPEG_EXPORT_API __declspec(dllexport)
    #    else
    #      define LIBJPEG_EXPORT_API __declspec(dllimport)
    #    endif
    #  endif
    #else
    #  define LIBJPEG_EXPORT_API
    #endif
    
    Run Code Online (Sandbox Code Playgroud)

    libjpeg源文件夹中名为win32_exports.h的文件中.这是一个非常标准的文件,用于处理.dll导出. 接下来,将其添加到项目中:在解决方案资源管理器中,RClick 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 "win32_exports.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.
    
    Run Code Online (Sandbox Code Playgroud)

    以上是差异.请参阅[SO]:从PyCharm Community Edition中鼠标右键单击上下文菜单运行/调试Django应用程序的UnitTests?(@CristiFati的回答)(修补utrunner部分)关于如何在Win上应用补丁(基本上,每个以 一个"+"符号开头的行进入,并且每个以一个" - "符号开头的行 都会消失).但是,由于这些变化微不足道,因此也可以手动完成.需要更改的文件是jmorecfg.h(需要2件事):

    • 在开头包含新文件(__declspec(dllexport))
    • 修改第251行(替换#include "win32_exports.h"#define EXTERN(type) extern type)

    我认为这一步是某种解决方法(获得者),但正如我所说,"真实的东西"只需要太多的工作(和时间).

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

    编辑项目设置(再次注意平台/配置),选择配置属性 - > C/C++ - >预处理器 - >预处理器定义,并将旧值(在我的情况下:)替换#define EXTERN(type) extern LIBJPEG_EXPORT_API typeWIN32;NDEBUG;_LIB;_CRT_SECURE_NO_WARNINGS.我做的是:

    1. 删除 _LIB
    2. 添加 LIBJPEG_EXPORTS
    3. 一些转变

    [MS.Docs]:/ D(预处理器定义)可能包含一些有用的信息.

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

3.测试DLL

  • 这是可选的,我这样做是为了确保我到目前为止做的事情并非徒劳
  • 通过测试,我只提到构建和运行,这意味着我没有进行任何功能测试(从.dll导出的函数实际上做了他们应该做的任何事情)

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

  1. 1 的事,是建立它的现有版本的配置.但是,由于对jpeg库进行了更改,因此不会构建OOTB(会出现链接器错误).为了摆脱它们,编辑它的设置,预处理器定义(就像在上一步中一样),并添加JPEG_STATIC(不要忘记分隔符(;)).

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

  2. 构建一个使用我们的.dll的新可执行文件:

    • 就像在jpeg库中的情况一样,创建一个新配置:Release-DLL(确保执行所有步骤,但不要更改它)
    • 只需要进行一项更改:让链接器知道我们构建.lib文件的位置.转到项目设置,配置属性- >链接器- >输入- >附加依赖:1 发布\ jpeg.lib.显然,路径不正确,所以我们需要用Win32-Release-DLL替换Release(当然你可以使用VStudio宏(用于平台/配置)).可以将[MS.Docs]:.Lib文件检查为链接器输入.

全部保存并构建.构建成功后,在djpeg\Release-DLL下,应该有一个djpeg.exe文件.尝试运行它将失败,因为它找不到jpeg.dll.修复此问题,方法是将jpeg.dll复制到(检查[MS.Docs]:动态链接库搜索顺序的语义):

  • djpeg.exe的文件夹
  • %PATH% env var 中的一个文件夹(或者反过来,将jpeg.dll文件夹附加到%PATH%)

同样,您可以使用Dependency Walker检查2个可执行文件(但是大小差异足以说明:第二个 djpeg.exe明显更小),看看哪个依赖于jpeg.dll.无论如何,这是我的计算机上的输出(是的,Dependency Walker也可以充当cmdline :)):

e:\Work\Dev\StackOverflow\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\StackOverflow\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\StackOverflow\q044450813\src\libjpeg-libjpeg-9b>type static.txt | findstr -i "jpeg.dll"

e:\Work\Dev\StackOverflow\q044450813\src\libjpeg-libjpeg-9b>type dynamic.txt | findstr -i "jpeg.dll"
     [   ] e:\work\dev\stackoverflow\q044450813\src\libjpeg-libjpeg-9b\djpeg\release-dll\JPEG.DLL
[   ]  e:\work\dev\stackoverflow\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
Run Code Online (Sandbox Code Playgroud)


@ EDIT0:

我也是: