为什么我的程序要求 OpencV 的 .dll,即使我 link 静态地反对它的 .lib

Why does my program ask for OpencV's .dll even though I link statically against its .lib

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

我 link 针对 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 库已添加到依赖项中:

并在 linking 步骤中使用:

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)

但他们没有任何区别

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

lib /list foo.lib

(有关详细信息,请参阅 here) to determine the type of the lib. If it is a static lib it will show you some .obj files used while creating the lib. If it is an import lib, it will show you the required .dll you should provide. The dll itself should in one of the search paths. It can become quite complex if you want to use some special path, but the simplest is to put it into the same folder as the executable which is using it or the system folder. Read Dynamic-Link Library Search Order。静态库和隐式动态库都需要一个头文件和一个 .lib 文件。

第三种方式(动态显式)你必须使用LoadLibrary[AW], GetProcAddress and FreeLibrary。这里指定dll的路径,使用dll"directly"。您没有任何头文件或 .lib 文件,但必须 确切地 了解函数的命名方式和声明方式(return 和参数值类型),否则您的程序不会按预期工作。

您可以在 MSDN.

上找到有关 dll 的更多信息