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

2024-01-24

我想构建 libjpeg 9b 的 DLL 版本。根据文件here https://msdn.microsoft.com/en-us/library/ms235636.aspx,看来我们需要添加一个预处理器__declspec(dllexport) or __declspec(dllimport)在声明每个要导出的函数之前,除了将配置类型设置为“动态库(.dll)”之外。但这并不是一件容易的事,因为 libjpeg 中有很多函数。那么,是否有任何捷径或解决方法可以在不修改或只修改 jpeglib.h 的情况下构建 DLL libjpeg?是否有可用的 libjpeg 9b 的 DLL 就绪源?我在 Windows 7 64 位上使用 Visual Studio 2015。感谢您的回答。

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


已发布的版本(静态/动态)[GitHub]:CristiFati/Prebuilt-Binaries - (主)Prebuilt-Binaries/LibJPEG https://github.com/CristiFati/Prebuilt-Binaries/tree/master/LibJPEG.



就像现在几乎所有的软件一样,LibJPEG还托管于[GitHub]: winlibs/libjpeg - libjpeg-9b https://github.com/winlibs/libjpeg/releases/tag/libjpeg-9b。我从两个地方下载了它,进行了比较,只发现了一些细微的差异(源代码中没有)。我将解释一下GitHub版本。不幸的是,没有关于此的演练,所以我必须查看一些文件才能弄清楚必须做什么。以下是步骤列表:

1.准备地面

1st thing is to extract the compressed (.zip / .tar.gz) file content into a folder (and have a Cmd console opened there). That folder contains a bunch of files. The 1st one that we need is makefile.vc. As it name suggests, it's a Makefile that consists of a series of rules/instructions used in general to build stuff.

作为评论,我正在使用VStudio(社区)2015 (14)用于此任务(但对于较新的版本应该没有差异)。

处理的工具Makefiles is NMake ([MS.Docs]:NMAKE 参考 https://learn.microsoft.com/en-us/cpp/build/nmake-reference?view=vs-2015)。我们需要根据该文件调用它。NMake位于 ”${VSTUDIO_INSTALL_DIR}\VC\bin\nmake.exe" (the (Nix style) 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命令行工具,最好是:

  • Use VCVarsAll(那是一个 (batch)设置一些的工具env vars like %PATH%, %包括%, %LIB%,...),所以所有的VStudio工具无需完整路径即可使用。但由于它也位于“%VSTUDIO_INSTALL_DIR%\VC\vcvarsall.bat“ (查看[SO]:链接到 CRT(未解析的外部符号 WinMainCRTStartup)(@CristiFati 的回答) https://stackoverflow.com/a/71872682/4788546有关更多详细信息),不值得花费精力去查找/调用它

  • Use VS2015工具命令提示符 from 开始菜单(这基本上称为VCVarsAll)

  • [MS.Docs]:在命令行上构建 https://learn.microsoft.com/en-us/cpp/build/building-on-the-command-line?view=vs-2015包含有关此主题的更多详细信息

现在我们知道在哪里NMake找到了,让我们运行:

"${VSTUDIO_INSTALL_DIR}\VC\bin\nmake.exe" /f makefile.vc setup-v10

(别忘了附上NMake的路径在双引号("),特别是如果它包含SPACEs).

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

  • 很可能遇到的一种:致命错误 U1052:找不到文件“win32.mak”- 查看[SO]:Visual Studio NMake 构建失败并显示:致命错误 U1052:找不到文件“win32.mak”(@CristiFati 的回答) https://stackoverflow.com/a/73167842/4788546

setup-v10 is a Makefile target, which simply renames some of the files in the folder (frankly, I don't know why the files aren't like already renamed in the 1st place).

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

  • jpeg.sln- 其中包含一个项目:

    • jpeg.vcxproj- 这是负责构建库的项目
  • apps.sln- 其中包含一堆项目(我不知道/关心他们做什么):

    • djpeg.vcxproj- 这是我要提到的唯一一个,因为我将使用它来测试构建的库

2. 构建jpeg library

The 1st thing to notice is that the solution / project files generated in the previous section are for VStudio 2010. But that's not a problem, since VStudio 2015 is able to handle them (when loading them, it will do all the necessary conversions to bring them up to date).

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

  • 它只有Win32(32 位或x86) 平台

    • 它只有Release配置
  • 正如您已经提到的,它构建了一个静态库

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

2.1 构建jpeg .dll

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

  • 从菜单中选择构建 -> 配置管理器...

  • 在弹出的对话框中,向上点击Release组合框并选择

  • In the 新解决方案配置对话框中,为新配置选择一个名称:我选择发布DLL(从现在起我就要依赖这个名字了)

  • 确保选择Release in the 从以下位置复制设置组合框

  • Check 创建新的项目配置

按下后OK,新的发布DLL配置将相同于Release。下一步是对其进行必要的更改,以实现我们的目标。RClick on the jpeg项目在解决方案浏览器(在左侧VStudio窗口),然后选择特性:

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

  • 蓝色:Platform / 配置 pair:

    • 正在修改(在最上面的对话框中)

    • 活跃(在VStudio主窗口在后面)

    修改一些时Platform / 配置设置确保它是活动的(蓝色矩形中的数据是相同的),否则您会用头撞墙,并浪费时间试图找出为什么看起来正确的东西无法按预期工作。我认为,当弹出这个对话框时,应该有active值,但情况并非总是如此。

  • 红色:项目should被修改(或至少需要注意):

    • 配置类型显然应该是动态库(.dll)

    • 平台工具集应该视觉工作室 2015(我提到这一点是因为它碰巧打开了一个VStudio 2010项目与VStudio2015,并且它保留了旧的工具集,并继续使用它进行构建,但前提是您安装了两个版本)

  • 绿色:建议修改的项目。这些只是文件夹。注意$(平台)变量(我将其用作一种很好的做法),在为多个平台(例如,Win32 and x64)

Save All并构建。构建成功后,新建一个文件夹Win32-发布-DLL就会出现,和前一个一样,它会包含一堆文件plus jpeg.dll。人们可能会认为事情已经完成,但事实并非如此。所有的代码都是编译/构建 in the .dll,但它是未出口, 所以.dll几乎无法使用。你可以检查很多.dll (or .exe) 属性打开它依赖步行者 http://www.dependencywalker.com(或较新的[GitHub]: lucasg/依赖项 https://github.com/lucasg/Dependencies)。您可以查看以下屏幕截图[SO]:Excel VBA,无法从 DLL 文件中找到 DLL 入口点(@CristiFati 的回答) https://stackoverflow.com/a/44177222/4788546- 在我们的例子中,导出区域将是空的。

最后一点:如果您认为将来您需要为其他平台构建(x64, 甚至ARM),并且您还需要进行一些调试(添加Debug配置),添加Debug配置下Win32平台first, and 只有那时创建新平台Win32,否则您需要添加Debug添加之前创建的每个平台的配置Debug配置为Win32.

2.2 导出数据.dll

正如注释:除了__declspec(dll导出)方法,还有另外 2 个(在处理来自Win .dlls):

  • 将导出列表作为参数传递给链接器([MS.Docs]:/EXPORT(导出函数) https://learn.microsoft.com/en-us/cpp/build/reference/export-exports-a-function?view=vs-2015)

  • 将它们枚举到[MS.Docs]:模块定义文件 https://learn.microsoft.com/en-us/previous-versions/ms925051(v=msdn.10)

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

  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 in the libjpeg源文件夹。这是一个非常标准的头文件,处理.dll出口。
    接下来,将其添加到项目中:解决方案浏览器, RClick on 头文件 -> 添加 -> 现有项目...

  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.
    

    上面是一个diff. See [SO]:从 PyCharm 社区版中的鼠标右键单击上下文菜单运行/调试 Django 应用程序单元测试? (@CristiFati 的回答) https://stackoverflow.com/a/42989490/4788546 (打补丁utrunner部分)了解如何应用补丁Win(基本上,每一行以one "+"标志进入,每行以one "-"标志熄灭)。但是,由于更改很小,因此也可以手动完成。需要更改的文件是jmorecfg.h(需要 2 件事):

    • 在开头包含新文件 (#include "jexport.h")

    • 修改第251行(替换#define EXTERN(type) extern type by #define EXTERN(type) extern LIBJPEG_EXPORT_API type)

    我认为这一步是某种解决方法(gainarie),但正如我所说,“真正的事情”只是需要太多的工作(和时间)。

  3. 告诉compiler考虑我们的改变

    编辑项目设置(再次小心Platform / 配置), 选择配置属性 -> C/C++ -> 预处理器 -> 预处理器定义并替换旧值(在我的例子中:WIN32;NDEBUG;_LIB;_CRT_SECURE_NO_WARNINGS) to WIN32;LIBJPEG_EXPORTS;_CRT_SECURE_NO_WARNINGS;NDEBUG。我所做的是:

    1. Adding LIBJPEG_EXPORTS

    2. Removing _LIB

    3. 有些转移

    [MS.Docs]:/D(预处理器定义) https://learn.microsoft.com/en-us/cpp/build/reference/d-preprocessor-definitions?view=vs-2015可能包含一些有用的信息。

    As a 边注,经过上述更改后,原始(或“正常”)行为(Release配置)不会OK(它会生成一堆警告,但这在技术上是不正确的)。那是因为我不想依赖_LIB宏来区分静态/动态库构建。为了把事情理顺,add LIBJPEG_STATIC in the 预处理器定义 for Release配置(遵循与上述相同的程序)。

Save All并构建。构建成功后,jpeg.dll被覆盖了,更重要的是:一个新文件jpeg.lib将被创建;这告诉我们jpeg.dll出口东西。您可以使用以下命令再次检查依赖步行者.

3. 测试.dll

  • 这是可选的,我这样做是为了确保我到目前为止所做的事情没有白费

  • 通过测试,我只指构建和运行,这意味着我不做任何事情功能测试(从导出的函数.dll实际上做他们应该做的事情)

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

  1. 1st thing to do, is to build it for the existing Release configuration. But, because of the changes done to jpeg library, it won't build OOTB (there will be linker errors). In order to get rid of them, edit its settings, the Preprocessor Definitions (just like in the previous step), and add LIBJPEG_STATIC (don't forget the separator (;)).

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

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

    • 就像在jpeg库的案例,创建一个新配置:发布DLL(确保完成所有步骤,但不要更改)

    • There's only one change required: let the linker know where we built our .lib file. Go to project settings, Configuration Properties -> Linker -> Input -> Additional Dependencies: the 1st is Release\jpeg.lib. Obviously, the path is not correct, so we need to replace Release by Win32-Release-DLL (of course you could use VStudio macros (for Platform / Configuration)). Might check [MS.Docs]: .Lib Files as Linker Input https://learn.microsoft.com/en-us/cpp/build/reference/dot-lib-files-as-linker-input?view=vs-2015.

Save All并构建。构建成功后,在djpeg\Release-DLL,应该有一个djpeg.exe文件。尝试运行它会fail,因为找不到jpeg.dll。通过复制来解决这个问题jpeg.dll去检查[MS.Docs]:动态链接库搜索顺序 https://learn.microsoft.com/en-gb/windows/desktop/Dlls/dynamic-link-library-search-order对于语义):

  • The djpeg.exe的文件夹

  • 中的文件夹之一%PATH% env var(或者相反,附加jpeg.dll文件夹到%PATH%)

Again, you can check the 2 executables with Dependency Walker (but the size difference says enough: the 2nd djpeg.exe is significantly smaller), to see which one depends on the jpeg.dll. Anyway, here's the output on my computer (yes, Dependency Walker can act as a CmdLine as well :) ):

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


Update #0

我还:

  • 将更改提交至[GitHub]: winlibs/libjpeg - Win:将 libjpeg 构建为 dll https://github.com/winlibs/libjpeg/pull/3(拒绝了)

  • 尝试联系JPEG 参考 https://jpegclub.org/reference(几次),但击中后形态冻结SEND(甚至留了一夜,但运气不佳)

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何构建 libjpeg 9b 的 DLL 版本? 的相关文章

随机推荐

  • 在 Excel 中将超链接转换为 HTML 代码

    我的 Excel 文件中有一列超链接 我想将它们转换为各自的 HTML 代码 a href http www example com Link Name a 我找到了仅提取链接 作为文本 的方法 但我需要将整个 HTML 代码作为文本来替换
  • 如何在.NET 中解析 UDP 数据包?

    如何在 NET 中解析 UDP 数据包 我使用 PCap Net 捕获数据包 在本例中为 UDP 数据包 我可以通过 PcapDotNet packets Ethernet IpV4 Udp 从 PCap net 对象访问这些数据包 我如何
  • Jquery 列表框更改事件不会在键盘滚动时触发

    我有一个 HTML 表单上的简单列表框和这个非常基本的 jQuery 代码 Toggle visibility of selected item selCategory change function prashQs addClass hi
  • 在设备的默认浏览器中打开链接。人行横道 Android 应用程序

    我正在使用 HTML 和 JavaScript 创建适用于 Android 设备的应用程序 我正在使用 Crosswalk 15 44 384 12 将其捆绑到 Android 应用程序中 这几乎创建了一个内置 Web 浏览器的 Andro
  • 可以嵌套 HTML 表单吗?

    是否可以像这样嵌套 HTML 表单
  • 是否可以使用egrep来匹配某个范围内的数字?

    有没有办法grep egrep两组数字之间 egrep SomeText 19999 22000 some file txt 它不返回值 我预计 SomeText 19999 ffuuu SomeText 20001 ffuuu SomeT
  • shell pipeline 如何处理无限循环

    每当我需要限制 shell 命令输出时 我都会使用 less 对结果进行分页 cat file with long content less 它工作得很好 但我很好奇的是 即使输出永远不会结束 less 仍然有效 请考虑将以下脚本放在inf
  • 使用谷歌翻译 API 的值无效 (400)

    我的要求有什么问题吗 我有俄语字符串 string 我想用 google API 将其翻译为乌克兰语 我对字符串进行编码 q urlencode string 我请求谷歌API 作为回应 我得到 error errors domain gl
  • 在 ng-view 上滚动时,无尽滚动在 AngularJS 中不起作用

    我正在使用类似的代码this http jsfiddle net vojtajina U7Bz9 在 AngularJS 中创建无限滚动效果 我尝试通过移动可滚动容器的内容 在本例中为ul 到一个单独的 html 文件 然后使用 ng vi
  • ios:显示可变长度、多行文本的最佳方式

    我计划从文本文件加载多段落内容并将其显示在用户界面上 我将从几个文本文件之一加载 并且不会提前知道文本的长度 我的第一个想法是在 UIScrollView 中使用 UILabel 然而 似乎 UILabel 不能根据它包含的行数进行扩展 它
  • 如何在d3.js的Pack Layout中插入饼图?

    大家好 我想在我的包布局中添加饼图 而不是简单的圆圈 假设这是我的饼图数据和饼图布局 var data 2 3 4 5 var 弧 d3 svg arc outerRadius 50 innerRadius 0 var 饼 d3 layou
  • 就数据挖掘和可视化工具支持而言,日志事件的最佳 XML 格式是什么?

    我们希望能够从 Java 应用程序创建日志文件 该文件适合稍后通过工具进行处理 以帮助调查错误并收集性能统计数据 目前 我们使用传统的 日志内容 可能会或可能不会被展平为文本形式并附加到日志文件中 但这最适合人类读取的少量信息 经过仔细考虑
  • c strcmp 源代码

    int strcmp const char s1 const char s2 int ret 0 while ret unsigned char s1 unsigned char s2 s2 s1 s2 if ret lt 0 ret 1
  • 如何避免 ReactJS 中的 jQuery 调用

    我知道 JQuery 是 ReactJS 中的一种代码味道 因为它遍历整个 DOM 来完成它的工作 但是 我发现有些地方很难不使用它 这是一个例子 如果可能的话 我想找到一种更好的方法 我只是想根据字段是否填充来显示或隐藏 div 上的消息
  • redux 中有 OOP 的地方吗?

    我已经使用面向对象编程实践 25 年了 并在过去 5 年里尝试转向函数式编程 但当我尝试做一些复杂的事情时 我的想法总是倾向于 OOP 尤其是现在 ES6 支持像样的OOP 语法 这是我构建东西的自然方式 我现在正在学习 Redux 并且我
  • 来电显示检测:不适用于某些手机

    当有人打电话时 我使用以下方法来检测来电显示 在表单加载时我设置以下代码 this serialPort1 PortName COM3 this serialPort1 BaudRate 9600 this serialPort1 Data
  • mysql UPDATE 比 INSERT INTO 快吗?

    这更多的是一个理论问题 如果我运行 50 000 个插入新行的查询和 50 000 个更新这些行的查询 哪一个将花费更少的时间 插入会更快 因为使用更新 您需要首先搜索要更新的记录 然后执行更新 尽管这似乎不是一个有效的比较 因为您永远无法
  • 在 R parallel::mcparallel 中,是否可以限制任一时间使用的核心数量?

    在 R 中 mcparallel 函数在parallel每次调用包时 它都会将新任务分叉给工作人员 例如 如果我的机器有 N 个 物理 核心 并且我分叉了 2N 个任务 那么每个核心都会开始运行两个任务 这是不可取的 我宁愿能够开始在 N
  • 在 React Native 中创建自定义底部选项卡导航器

    大家好 我想在 React Native 中创建时尚且自定义的底部选项卡导航 任何人都可以知道如何创建上面提到的内容 const customTabBarStyle activeTintColor 0091EA inactiveTintCo
  • 如何构建 libjpeg 9b 的 DLL 版本?

    我想构建 libjpeg 9b 的 DLL 版本 根据文件here https msdn microsoft com en us library ms235636 aspx 看来我们需要添加一个预处理器 declspec dllexport