error LNK2001: 无法解析的外部符号 “__declspec(dllimport) XXX 解决办法

1. 背景

在生成某个项目的时候出现Bug

无法解析

error LNK2001: 无法解析的外部符号 "__declspec(dllimport) public 解决办法

xxx.obj : error LNK2001: 无法解析的外部符号 "__declspec(dllimport) public: bool __cdecl xxx::xxx::xxx::xxx...

2. 原因

(1)出现了 "LNK2001: 无法解析的外部符号",这表明在链接阶段,编译器找不到这些函数和析构函数的定义。

(2)

  • 这种情况通常是由于以下几种原因导致的:
    • 没有正确包含定义这些函数的源文件或库文件。也许这些函数是在另一个库或者源文件中定义的,但是项目设置没有正确地将其包含进来进行链接。
    • 函数定义所在的库没有被正确链接。如果这些函数是在一个动态链接库(DLL)中定义的,可能没有正确设置链接器选项来链接该 DLL。
    • 函数的声明和定义不匹配。例如,函数的参数类型、返回值类型或者函数签名在声明和定义过程中出现了不一致的情况,这也会导致链接器无法正确识别函数定义。
  1. 解决办法:
  • 检查库和头文件包含情况
    • 确认包含了定义这些函数的头文件。在xxx.cpp(或相关源文件)中,检查是否包含了正确的头文件来声明xxx类及其成员函数。例如,如果这些函数是在一个名为xxxh的头文件中声明的,确保有类似于#include "SurfaceReconstructionByPointCloud.h"的语句,并且头文件路径设置正确。
    • 检查项目的库依赖。如果这些函数是在一个库中定义的,确保在项目设置中正确地添加了该库的引用。在 Visual C++ 中,你可以在项目属性 - > 链接器 - > 输入 - > 附加依赖项 中添加库文件的名称(如McsfAlgoUIBotSpinePlanning.lib)。同时,要确保库文件的路径在项目属性 - > 链接器 - > 常规 - > 附加库目录中设置正确。
  • 检查函数签名一致性
    • 对比函数声明和定义的签名。检查xxx类的构造函数、析构函数和函数在声明和定义处的返回值类型、参数类型和参数个数是否完全一致。
  • 重新生成库和依赖项
    • 如果对函数所在的库文件 进行了修改,确保重新生成该库文件 。有时候,库文件可能没有正确更新,导致链接器找不到最新的函数定义。在这种情况下,重新编译和生成相关的库项目,然后在主项目中再次进行链接操作
  1. 总结

对于我的问题,后来是通过重新生成库和依赖项 解决的。

  1. 补充:

.cpp, .h, .obj, .dll, .lib, .sln的相互关系

.cpp 文件是代码实现主体,编译成.obj 目标文件,.h 文件用于声明函数等供.cpp 使用,.lib 静态库和.dll 动态库提供可复用代码。.obj 与库文件经链接生成最终可执行文件,.sln 则是管理包含相关项目的解决方案文件,统筹项目编译等事宜

  1. 库文件(.lib 和.dll)

    • 静态库(.lib)
      • 定义:静态库是一组目标文件(.obj)的集合,在链接阶段,编译器会把静态库中的代码复制到最终的可执行文件中。它就像是一个代码仓库,包含了许多可以被重复使用的函数和变量的定义。例如,如果你有一个数学库,里面有各种数学运算函数,将其编译为静态库后,在其他项目中使用这些数学函数时,函数的代码会直接被整合到最终的可执行文件中。
      • 作用:静态库的主要优点是可移植性好,因为所有需要的代码都在可执行文件中,不需要额外的库文件就可以运行。但是,它也会使可执行文件变得比较大,因为会复制库中的代码。
    • 动态库(.dll)
      • 定义:动态链接库(DLL)也是包含了函数和变量定义的库文件,但它在运行时才会被加载。当程序运行到需要使用 DLL 中的函数时,操作系统会将 DLL 加载到内存中,并执行其中的函数。例如,Windows 操作系统中的许多系统功能都是通过 DLL 提供的,如 user32.dll 包含了用于创建和管理用户界面的函数。
      • 作用:动态库可以被多个程序共享,这样可以节省内存和磁盘空间。如果多个程序都使用同一个动态库,只有一份 DLL 文件的副本会在内存中被加载。不过,它也有一些缺点,比如需要确保 DLL 文件在运行时能够被正确找到,否则程序会出现找不到 DLL 的错误。
  2. 源文件(.cpp)和头文件(.h)

    • 源文件(.cpp)
      • 定义 :.cpp 文件是 C++ 程序的主要源文件,其中包含了函数的实际定义、变量的定义和赋值,以及各种语句来实现程序的逻辑。例如,McsfAlgoSurfaceReconstruction.cpp文件中定义了SurfaceReconstructionByPointCloud类的成员函数的具体实现代码,包括前面提到的GetResult函数的具体运算过程。
      • 作用:它是程序功能的实际实现部分,编译器会将.cpp 文件编译成目标文件(.obj)。
    • 头文件(.h)
      • 定义 :.h 文件主要用于声明函数、类、变量等。它就像是一个接口文件,告诉其他.cpp 文件可以使用哪些函数和类,以及它们的参数和返回值类型等信息。例如,SurfaceReconstructionByPointCloud.h文件会声明SurfaceReconstructionByPointCloud类的构造函数、析构函数和GetResult等成员函数,但是不会包含这些函数的具体实现代码。
      • 作用:头文件用于在多个源文件之间共享声明信息,避免了重复定义的问题。当一个.cpp 文件需要使用另一个.cpp 文件中定义的函数或类时,通过包含对应的头文件来获取声明信息。
  3. 目标文件(.obj)

    • 定义 :目标文件是编译器将.cpp 源文件编译后生成的中间文件。它包含了机器代码,这些机器代码是对源文件中的 C++ 代码进行编译后的结果,但还没有进行链接操作。例如,McsfAlgoSurfaceReconstruction.obj文件是McsfAlgoSurfaceReconstruction.cpp文件编译后的产物。
    • 作用:目标文件是链接过程的基本单位,链接器会将多个目标文件以及库文件(.lib 或.dll)链接在一起,生成最终的可执行文件或库文件。
  4. 解决方案文件(.sln)

    • 定义 :.sln 文件是 Visual Studio 中的解决方案文件,它是一个项目的组织容器。一个解决方案可以包含多个项目(.vcxproj),这些项目可以是可执行程序项目、库项目等。例如,你重新生成的那个包含SurfaceReconstructionByPointCloud类所在文件对应的.sln 文件,它可能包含了一个库项目,这个库项目用于生成相关的.lib 或.dll 文件。
    • 作用:它用于管理项目之间的关系,包括项目的依赖关系、编译顺序等。在构建项目时,Visual Studio 会根据.sln 文件中的设置来决定如何编译各个项目,以及如何处理项目之间的依赖关系。
相关推荐
以卿a1 小时前
C++ 模板初阶
开发语言·c++
黑不溜秋的7 小时前
C++ 设计模式 - 策略模式
c++·设计模式·策略模式
Dream it possible!9 小时前
LeetCode 热题 100_在排序数组中查找元素的第一个和最后一个位置(65_34_中等_C++)(二分查找)(一次二分查找+挨个搜索;两次二分查找)
c++·算法·leetcode
柠石榴9 小时前
【练习】【回溯No.1】力扣 77. 组合
c++·算法·leetcode·回溯
王老师青少年编程9 小时前
【GESP C++八级考试考点详细解读】
数据结构·c++·算法·gesp·csp·信奥赛
澄澈天空11 小时前
C++ MFC添加RichEditControl控件后,程序启动失败
c++·mfc
Lzc77411 小时前
C++初阶——简单实现vector
c++·简单实现vector
一个小白112 小时前
C++——list模拟实现
开发语言·c++
程序员老舅12 小时前
C++ Qt项目教程:WebServer网络测试工具
c++·qt·测试工具·webserver·qt项目·qt项目实战
靡不有初11112 小时前
CCF-CSP第18次认证第一题——报数【两个与string相关的函数的使用】
c++·学习·ccfcsp