【问题标题】:Why does my program ask for OpencV's .dll even though I link statically against its .lib为什么我的程序要求 OpencV 的 .dll,即使我静态链接到它的 .lib
【发布时间】:2016-07-26 14:30:54
【问题描述】:

我正在构建一个使用 OpenCV 3.1 与 CMake 3.5 和 Visual Studio 2015 x64 的小程序。

我链接到 OpenCV 的 .lib 文件,但是当我尝试运行该程序时,我收到一个关于缺少 DLL 的错误:

这是我的CMakeLists.txt

cmake_minimum_required(VERSION 3.5)
project (MyProj)

set(CMAKE_FIND_LIBRARY_SUFFIXES, ".lib")

#Boost
set(Boost_USE_STATIC_LIBS        ON)
set(Boost_USE_MULTITHREADED      ON)
set(Boost_USE_STATIC_RUNTIME    OFF)
find_package(Boost REQUIRED system thread serialization filesystem)

#OpenCV
find_package(OpenCV REQUIRED)

add_executable(
        MyApp
        main.cpp
)

target_include_directories(MyApp PRIVATE
        ${OpenCV_INCLUDE_DIRS}
        ${Boost_INCLUDE_DIRS}
)

target_link_libraries(MyApp
        ${OpenCV_LIBRARIES}
        ${Boost_LIBRARIES}
)

OpenCV_DIR 设置为C:\tools\opencv3\build\x64\vc14\lib,它具有include/ opencv_world310.lib opencv_world310d.lib OpenCVConfig.cmake OpenCVModules.cmake OpenCVModules-debug.cmake OpenCVModules-release.cmake,是从OpenCV v3.1 的官方Windows 二进制文件中提取的

然后我用cmake . -G "Visual Studio 14 Win64"生成VS解决方案

如您所见,OpenCV 库已添加到依赖项中:

and 用于链接步骤:

Link:
  C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin\x86_amd64\link.exe /ERRORREPORT:QUEUE /OUT:"C:\...\Debug\MyApp.exe" /
  INCREMENTAL /NOLOGO kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comdlg32.lib 
  advapi32.lib C:\tools\opencv3\build\x64\vc14\lib\opencv_world310d.lib C:\tools\opencv3\build\x64\vc14\lib\opencv_world310d.lib 
  C:\tools\opencv3\build\x64\vc14\lib\opencv_world310d.lib C:\tools\opencv3\build\x64\vc14\lib\opencv_world310d.lib 
  C:\tools\opencv3\build\x64\vc14\lib\opencv_world310d.lib C:\tools\opencv3\build\x64\vc14\lib\opencv_world310d.lib 
  C:\tools\opencv3\build\x64\vc14\lib\opencv_world310d.lib C:\tools\opencv3\build\x64\vc14\lib\opencv_world310d.lib 
  C:\tools\opencv3\build\x64\vc14\lib\opencv_world310d.lib C:\tools\opencv3\build\x64\vc14\lib\opencv_world310d.lib 
  C:\tools\opencv3\build\x64\vc14\lib\opencv_world310d.lib C:\tools\opencv3\build\x64\vc14\lib\opencv_world310d.lib 
  C:\tools\opencv3\build\x64\vc14\lib\opencv_world310d.lib C:\tools\opencv3\build\x64\vc14\lib\opencv_world310d.lib 
  C:\tools\opencv3\build\x64\vc14\lib\opencv_world310d.lib C:\tools\opencv3\build\x64\vc14\lib\opencv_world310d.lib 
  C:\tools\opencv3\build\x64\vc14\lib\opencv_world310d.lib "C:\tools\boost_1_61_0\stage\lib\libboost_system-vc140-mt-gd-1_61.lib" 
  "C:\tools\boost_1_61_0\stage\lib\libboost_thread-vc140-mt-gd-1_61.lib" 
  "C:\tools\boost_1_61_0\stage\lib\libboost_serialization-vc140-mt-gd-1_61.lib" 
  "C:\tools\boost_1_61_0\stage\lib\libboost_filesystem-vc140-mt-gd-1_61.lib" 
  "C:\tools\boost_1_61_0\stage\lib\libboost_chrono-vc140-mt-gd-1_61.lib" 
  "C:\tools\boost_1_61_0\stage\lib\libboost_date_time-vc140-mt-gd-1_61.lib" 
  "C:\tools\boost_1_61_0\stage\lib\libboost_atomic-vc140-mt-gd-1_61.lib" /MANIFEST /MANIFESTUAC:"level='asInvoker' 
  uiAccess='false'" /manifest:embed /DEBUG /PDB:"C:/Users/.../Debug/MyApp.pdb" /SUBSYSTEM:CONSOLE /TLBID:1 /DYNAMICBASE /NXCOMPAT /
  IMPLIB:"C:/Users/.../Debug/MyApp.lib" /MACHINE:X64  /machine:x64 MyApp.dir\Debug\sheepface.obj MyApp.dir\Debug\source.obj
  MyApp.vcxproj -> C:\Users\...\Debug\MyApp.exe
  MyApp.vcxproj -> C:/Users/.../Debug/MyApp.pdb (Full PDB)

我已经尝试过设置魔法变量

set(OpenCV_STATIC ON)
set(BUILD_SHARED_LIBS     OFF)

但它们没有区别

【问题讨论】:

  • lib 是静态库还是 dll 的 lib?
  • 你必须链接到静态版本的opencv。在 prebuild openCV 文件夹中通常有 3 个文件夹,例如在我的 32 位 opencv 2.4.11 中有 x86/vc12/bin x86/vc12/libx86/vc12/staticlib 您必须选择 staticlib 文件夹中的库。
  • 所以对你来说应该是x64/vc14/staticlib/,如果该文件夹不存在,你必须自己编译静态链接的opencv。
  • 或多或少是对的……阅读implicit linking了解更多详情。
  • @grisevg 对于 Visual c++,共享库的典型过程是有一些头文件、一些库(在编译时需要)和一些 dll(在运行时需要)。您可能会找到一些关于在这种情况下需要/使用哪些库的信息。

标签: c++ visual-studio opencv cmake static-linking


【解决方案1】:

您可以通过三种不同的方式来创建和使用库;静态、动态隐式和动态显式。 library.lib 不一定是静态库,它将包含您预期的编译代码。它要么包含代码,要么(简单地说)包含由操作系统加载的所需 *.dll 的名称,以及指向此 dll 内函数的入口。如果你不知道特定库是什么类型的库,你可以使用

lib /list foo.lib

(参见here)来确定库的类型。如果它是一个静态库,它会显示一些在创建库时使用的 .obj 文件。如果它是一个导入库,它将显示您应该提供的所需 .dll。 dll 本身应该在搜索路径之一中。如果你想使用一些特殊的路径,它可能会变得相当复杂,但最简单的是将它放在与使用它的可执行文件或系统文件夹相同的文件夹中。阅读Dynamic-Link Library Search Order 了解更多详情。静态库和隐式动态库都需要一个头文件和一个 .lib 文件。

第三种方式(动态显式)您必须使用LoadLibrary[AW]GetProcAddressFreeLibrary。在这里,您指定 dll 的路径并“直接”使用 dll。您没有任何头文件或 .lib 文件,但必须确切了解函数是如何命名的以及它们是如何声明的(返回值和参数值类型),否则您的程序将无法按预期运行。

您可以在MSDN 上找到有关 dll 的更多信息。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-04-03
    • 2011-01-15
    • 2011-10-20
    • 2018-03-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多