OpenCV 2.4.1与Qt的静态链接

3

我使用MinGW和CMake编译了OpenCV 2.4.1的静态版本,没有出现错误。我勾选了“With_QT”选项。

我取消勾选了“BUILD_SHARED_LIBS”,然后执行了“mingw32-make”和“mingw32-make install”命令,顺利完成了构建。在opencv的lib文件夹中生成了一堆“.a”文件。

但是,当我在Qt中运行一个简单的应用程序时,通过设置“.pro”文件的“LIBS和INCLUDEPATH”参数后,却遇到了错误。

我还在“.pro”文件中添加了以下行:

CONFIG += -static -static-libgcc

我提供了上一行的错误:

F:\OpenCV2.4.1\opencv-static\install\lib\libopencv_highgui241.a(grfmt_jpeg2000.cpp.obj):grfmt_jpeg2000.cpp:(.text$_ZN2cv13Jpeg2KDecoder10readHeaderEv+0x4f):
undefined reference to `jas_image_decode'  collect2: ld returned 1
exit status  mingw32-make[1]: ***

[release\test.exe] Error 1 
mingw32-make: *** [release] Error 2  The process "C:/ming44/bin/mingw32-make.exe" exited with code %2. Error while building project test (target: Desktop) When executing build step 'Make'

更新

我发现出错只是在调用 highgui.hpp 方法时。比如当我使用 cv::imshow() 时出现以下错误:

F:\OpenCV2.4.1\opencv-static2\install\lib\libopencv_highgui241.a(window_w32.cpp.obj):window_w32.cpp:(.text$_ZL17icvCreateTrackbarPKcS0_PiiPFviEPFviPvES4_+0x5e1): undefined reference to `CreateToolbarEx@52'  collect2: ld returned 1
exit status  mingw32-make[1]: *** [release\test.exe] Error 1 
mingw32-make: *** [release] Error 2

有人能帮我解决这个问题吗。

谢谢


很明显,你忘记链接到libjasper,这是OpenCV的第三方依赖库。你是否已经构建过它了?如果是,那么也链接上它。我认为错误信息已经很明显了。例如,虽然我从未使用过OpenCV,但在浏览他们的代码库后,我立即知道了你的问题以及如何解决它。所以另一个问题是:你确定你理解链接工作的原理吗? - Alexander Shukaev
@Haroogan 我在构建opencv时勾选了BUILD_JASPER选项,但没有创建lib文件。我认为该过程类似于共享模式下的构建。 - Hamid Bazargani
看看CreateToolbarEx函数,向下滚动并查看该符号是在Comctl32.libComctl32.dll中定义的。现在,猜猜看?也许是时候链接其中一个(以便解决符号)了?副问题仍然未解决,因为你不能一遍又一遍地自己解决简单的问题。 - Alexander Shukaev
@Haroogan 谢谢。我知道静态链接是如何工作的。我的问题是如何找到应该链接哪个库.a文件来解决错误。我明白我需要链接Comct32.a,对吗?但是我在哪里可以找到它? - Hamid Bazargani
@Haroogan 你知道在哪里可以找到 vfw32.a 吗?因为我遇到了另一个需要它的错误:undefined reference to AVIStreamRelease@4' - Hamid Bazargani
显示剩余6条评论
1个回答

2

在我们进行修复过程中出现了许多问题,所以我会在这里尝试总结所有问题的答案。

未解决的符号


undefined reference to `jas_image_decode'

jas_image_decode符号在libjasper中定义(它是OpenCV的第三方依赖项)。要解决此问题,请链接到libjasper.a

undefined reference to `CreateToolbarEx@52'
CreateToolbarEx 符号是 Windows API 的一部分,因此在系统库中定义(这些库始终随着工具链提供,例如在您的情况下是 MinGW)。您可以通过查看 MSDN(向下滚动并查看DLL单元格)找到应链接哪个库以解析此类符号。在本例中,您可以看到Comctl32.lib,但是 MSDN 当然会以 Microsoft Visual C 工具链定义它们的格式发布库名称。由于您使用的是 MinGW 工具链,因此您需要将此名称转换为 Unix 库命名约定,并且在本例中,那就是libcomctl32.a
undefined reference to `AVIStreamRelease@4'

类似于之前的情况,我们在这里找到它(链接),并推断我们必须链接libvfw32.a
注意:这样的系统库路径(包含Windows API)总是由工具链自动搜索。因此,在编译/链接过程中不应提供-L选项,而只需提供库本身,即-lcomctl32
undefined reference to `cv::dft'

这又是来自OpenCV的一些组件(cv命名空间显然表明了这一点)。稍微搜索一下,就可以发现它在核心组件中定义。因此,要解决这个符号,需要链接到libopencv_core.a

方法


如何找出要链接的库以解决缺失的符号?

这里没有什么经验法则或直接的方法,而是需要一些技巧和经验积累。以下是一些示例:

  1. 例如,在CreateToolbarEx的情况下,我很容易猜到它属于Windows API,因为我认识到函数名的Windows API命名规范。因此,接下来我会在Google中键入CreateToolbarEx,跳转到相应的MSDN页面,向下滚动,查看库名称,将其(在脑海中)转换为Unix库命名规范(见上文),然后完成!

  2. OpenCV的情况更加棘手。OpenCV是第三方库,确定特定符号所在的库是否难以找到完全取决于提供的文档质量。尽管我可以看到OpenCV文档非常好,但仍然缺少每个符号的这些重要提示,这很遗憾。然而,我们(开发人员)必须能够应对这类问题,无论第三方库的文档有多烂,都要完成工作。

    这就是为什么始终使用文件内容搜索实用程序,例如grep(在Unix OS系列上流行,但在Windows中也可在MSYS分发中使用)。例如,在cv::dft的情况下,您可以在OpenCV源树的根目录中运行grep -r "void.*dft(" .,并迅速找到该符号的定义位置。之后,您需要推断包含cv::dft的文件属于哪个组件,但这应该很简单,只需要查看文件所在的目录即可。

结论


我发誓我从未在生活中使用过OpenCV,但正如您所看到的,我仍能够为您找到所有这些缺失的符号。因此,我们可以得出结论,搜索未解决的符号的建议技巧是相当可靠的。

最后,这些内容与OpenCV或Qt无关。你正在处理基本的程序员技能。如果你想成为一个高效的软件开发人员,能够快速解决日常例行事务,那么grep只是众多必不可少的工具之一,应该毫无疑问地成为你的工具库的一部分。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接