C++ 将程序链接到静态库,将自身链接到另一个库

C++ 将程序链接到静态库,将自身链接到另一个库,c++,visual-studio-2015,static-libraries,linker-errors,C++,Visual Studio 2015,Static Libraries,Linker Errors,我正在尝试在Windows(VS2015)上创建一个可以读取多种文件格式的程序(C++)。 为了做到这一点,我为MyProgram(主程序)和MyLibrary(包含多个不同文件格式的解析器)创建了一个解决方案。 在MyProgram中,我根据程序输入创建了一些解析器对象 一切都很顺利 然而,我尝试创建一个新的文件格式解析器(NiftiParser),它使用我下载并编译的外部库nifticlib(作为静态库) 所以我创建了我的NiftiParser类,它实现了一些方法,并且在内部调用niftic

我正在尝试在Windows(VS2015)上创建一个可以读取多种文件格式的程序(C++)。 为了做到这一点,我为MyProgram(主程序)和MyLibrary(包含多个不同文件格式的解析器)创建了一个解决方案。 在MyProgram中,我根据程序输入创建了一些解析器对象

一切都很顺利

然而,我尝试创建一个新的文件格式解析器(NiftiParser),它使用我下载并编译的外部库nifticlib(作为静态库)

所以我创建了我的NiftiParser类,它实现了一些方法,并且在内部调用nifticlib。 我在项目属性中添加了include dir和library dir,并且编译时没有错误。 然后我得到了一个已经创建的Parser.lib

然而,当我试图编译我的程序时,我得到了一个关于nifticlib库的一些函数未被解析的错误:

1>------ Build started: Project: Parser, Configuration: Debug x64 ------
1>  nifti_parser.cc
1>  Parser.vcxproj -> C:\Users\Laurent\Documents\C++-build\Projects\Parser\Debug\Parser.lib
2>------ Build started: Project: MyProgram, Configuration: Debug x64 ------
2>Parser.lib(nifti_parser.obj) : error LNK2019: unresolved external symbol nifti_image_read referenced in function "public: __cdecl NiftiParser::NiftiParser(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >)" (??0NiftiParser@@QEAA@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@Z)
2>C:\Users\Laurent\Documents\C++-build\Projects\Debug\MyProgram.exe : fatal error LNK1120: 1 unresolved externals
========== Build: 1 succeeded, 1 failed, 3 up-to-date, 0 skipped ========== 
1>----构建已启动:项目:解析器,配置:调试x64------
1> nifti_parser.cc
1> Parser.vcxproj->C:\Users\Laurent\Documents\C++-build\Projects\Parser\Debug\Parser.lib
2> ----构建已启动:项目:MyProgram,配置:调试x64------
2> Parser.lib(nifti_Parser.obj):错误LNK2019:函数“public:u cdecl NiftiParser::NiftiParser(class std::basic_string)”中引用的未解析外部符号nifti_image_读取(???0NiftiParser)@@QEAA@V?$basic_string@DU?$char_traits@D@性病病毒$allocator@D@2@@@std@@@Z)
2> C:\Users\Laurent\Documents\C++-build\Projects\Debug\MyProgram.exe:致命错误LNK1120:1未解析的外部
=========生成:1个成功,1个失败,3个最新,0个已跳过=============
我不知道为什么会这样。我试图将include的路径和nifticlib的library dir添加到我的程序项目中,但仍然存在一些问题

我不确定Visual Studio的编译/链接过程是什么(我以前在Linux上工作)

在我看来,只有当项目是静态库时,项目才会被编译,而链接部分只有在我试图编译程序本身时才会发生。 我说得对吗

另外,我不确定nifticlib应该链接到哪里。它应该是指向Parser.lib(在这里我使用库的函数)还是直接指向程序

多谢各位

另外,我还注意到我的nifticlib安装目录只包含header和.lib。我是否需要将.cpp也包含在其中,或者函数已经包含在.lib中

编辑:好的,显然构建一个静态库不会将它链接到任何东西,所以这可能就是为什么我在编译Parser.lib时没有遇到任何问题,因为它不会链接到nifticlib,但我的程序需要它。
因此,我应该只在解析器项目中包含nitficlib的include dir,并将Parser.lib和nifticlib放在我的MyProgram项目中吗?

Visual Studio的编译/链接与Linux工具链中的编译/链接没有太大区别。制作二进制文件(可执行文件或动态库)时,必须解析所有外部符号。在GCC中,必须向链接器指示库。命令行选项
-lmath
将告诉链接器从为库搜索设置的路径之一加载libmath.a,并在构建可执行映像时使用它

类似地,在VS中,不仅需要设置库目录的路径,还需要显式指示库文件。这通常在项目属性->链接器->输入->其他依赖项上完成。请注意,在Windows中,您只需输入完整的库名(MyLib.lib),而不是lib和.a之间的部分

还请注意,在Windows中,无法链接到动态库(.dll)的二进制文件。您将需要一个导入库(.lib)

创建静态库时,工具链不会解析外部参照。这就是为什么.lib在没有引用nifticlib的情况下编译得很好

至于应该在哪里链接nifticlib,这取决于具体情况。如果只有您的MyLibrary会使用nifticlib的函数,那么将其与静态库链接是明智的。但是,如果有一天您希望在MyProgram中直接使用nifticlib中的某些函数,那么在链接时可能会发生冲突。在这种情况下,您只需要在构建MyProgram时链接nifticlib

经验法则可以这样表述:

  • 如果只有MyLibrary使用nifticlib的标题,请将您的库链接到第三方库
  • 如果MyProgram还使用nifticlib的头文件(并实际从中调用函数),那么在构建MyProgram时最好链接nifticlib
这不是一个严格的描述,还有更复杂的情况,但基本情况是这样的

不,当您从不同的项目链接到静态库时,您不需要在构建静态库时使用cpp文件。library.cpp的内容已经以目标代码的形式包含在静态lib文件中


编辑:如果您希望将您的静态库与另一个静态库的外部链接,您需要转到“项目属性”->“库管理员”->“常规”->“其他依赖项”,并将external.lib放在那里

非常感谢您给出了这个非常完整的答案。我现在应该能弄明白了。还有一个问题,当您将库添加到输入->附加依赖项时,您需要指定完整路径,还是只指定库的名称?只指定名称。目录路径在VC++目录->库目录中指定。此外,如果MyLibrary和MyProgram项目都在同一个解决方案中,则根本不需要担心库目录。VS应该能够正确地找出它们,包括构建不同VER时的情况