C++ / VS 2012 - 多项目解决方案:一个项目中的链接器错误但另一个项目中没有

Posted

技术标签:

【中文标题】C++ / VS 2012 - 多项目解决方案:一个项目中的链接器错误但另一个项目中没有【英文标题】:C++ / VS 2012 - Multi-project solution: Linker errors in one project but not another 【发布时间】:2014-01-06 16:21:59 【问题描述】:

我有一个 MFC DLL,它被同一解决方案中的另一个项目使用。当从消费项目调用时,一切都正常工作,包括我将在下面写的函数。

我最近尝试为这个 DLL 组装一个单元测试应用程序,在最近添加到 DLL 之前一直运行良好(正如我所说,我已经证明在主项目中工作正常) .

注意:我还展示了 std::string 之一,因为它可能是相关的(并且已知在我的单元测试项目中工作)。

问题函数在头文件中声明如下:

#pragma once

#include <string>
#include <afx.h>

#ifdef CALIBRATIONTOOL_EXPORTS
#define CALIBRATIONTOOL_API __declspec(dllexport)
#else
#define CALIBRATIONTOOL_API __declspec(dllimport)
#endif

namespace MyCompanyName

    namespace CalibrationTool
    
        class FileUtils
        
        public:
            CALIBRATIONTOOL_API static bool FileExists(std::string filename);

            CALIBRATIONTOOL_API static bool FileExists(CString filename);

        ; // end class FileUtils
    ; // end namespace CalibrationTool
; // end namespace MyCompanyName

并在cpp中实现:

#include "stdafx.h"
#include "FileUtils.h"
#include "StringUtils.h"
#include <fstream>
#include <iostream>
#include <string>
#include <sstream>

#ifdef CALIBRATIONTOOL_EXPORTS
    #define CALIBRATIONTOOL_API __declspec(dllexport)
#else
    #define CALIBRATIONTOOL_API __declspec(dllimport)
#endif


namespace MyCompanyName

    namespace CalibrationTool
    
        bool FileUtils::FileExists(std::string filename) 
         

            std::string filenameAsStdString(filename);
            std::string filenameWithDoubleBackslashes = MyCompanyName::CalibrationTool::StringUtils::SingleToDoubleBackslash(filenameAsStdString);
            std::ifstream ifile(filenameWithDoubleBackslashes);
            bool exists = (bool)ifile;
            ifile.close();
            return exists;
         

        bool FileUtils::FileExists(CString filename)
        
            std::ifstream ifile(filename);
            bool exists = (bool)ifile;
            ifile.close();
            return exists;
        

    ; // end namespace CalibrationTool
; // end namespace MyCompanyName

到目前为止一切顺利。就像我说的,从主项目调用时测试正常。但是,在我的测试项目中,它是这样调用的:

bool FileUtilsTest::FileExistsTestCString()

    bool passed = true;

    CString definitelyExists = _T("C:\\Windows\\system.ini");
    CString definitelyDoesntExist = _T("C:\\NotMuchChanceThatThisFileExists.zut");

    if (MyCompanyName::CalibrationTool::FileUtils::FileExists(definitelyExists))
        
        // all is well
        CalibrationToolUnitTestsLogging::Write("Passed FileUtilsTest.FileExistsTestCString (files which exist). Successfully found C:\\Windows\\system.ini.");
    
    else
    
        // all is not well
        CalibrationToolUnitTestsLogging::Write("Failed FileUtilsTest.FileExistsTestCString (files which exist). Unable to find C:\\Windows\\system.ini.");
        passed = false;
    
    // (and more testing, e.g. for files which don't exist)

return passed;

我得到错误:

Error 4 error LNK2019: unresolved external symbol "__declspec(dllimport) public: static bool __cdecl MyCompanyName::CalibrationTool::FileUtils::FileExists(class ATL::CStringT&lt;char,class StrTraitMFC_DLL&lt;char,class ATL::ChTraitsCRT&lt;char&gt; &gt; &gt;)" (__imp_?FileExists@FileUtils@CalibrationTool@MyCompanyName@@SA_NV?$CStringT@DV?$StrTraitMFC_DLL@DV?$ChTraitsCRT@D@ATL@@@@@ATL@@@Z) referenced in function "private: bool __thiscall FileUtilsTest::FileExistsTestCString(void)" (?FileExistsTestCString@FileUtilsTest@@AAE_NXZ) C:\_SVN\CalibrationToolUnitTests\FileUtilsTest.obj

为了完整起见,这是我主项目中的工作代码:

if ((MyCompanyName::CalibrationTool::FileUtils::FileExists(exists)) && (!MyCompanyName::CalibrationTool::FileUtils::FileExists(doesntExist)))
    
        g_log.Write(log_debug, -1, _T("TEST"), _T("Seems fine."));
    
    else
    
        g_log.Write(log_debug, -1, _T("TEST"), _T("Something's up"));
    

谁能建议我哪里出错了?

【问题讨论】:

您是否将DLL-name.lib 文件包含在您的FileTestUtils 项目中? 我编辑了您的问题以显示可能的实际问题。您的 CString 专用于 char。很有可能您的 DLL 是专门为 wchar_t 构建的。请避免使用 _T() 之类的东西,或者仍然在“字符集”设置为多字节的情况下构建代码,Unicode 已经存在 21 年了。 谢谢汉斯。我继承了这段代码,并且大部分时间都是 C# 小伙子,所以我使用了前一个开发人员留给我的 CStrings 和 _T()s。尽管我正在重构并尝试在可能的情况下进行改进,但我仍然需要学习很多东西......例如CStrings 具有专业化(我认为它们的重点是没有专业化?),以及如何更改项目中的专业化。我会开始谷歌搜索! 【参考方案1】:

在 Visual Studio 10 中(我猜与 2012 相同)有 3 种不同的方式来添加依赖。

    手动 - 在项目设置中添加包含/库路径,以及 添加库。 新建(更喜欢这样做...) - 项目 -> 属性。 选择:通用属性-> 框架和参考。 按“添加参考”。现在选择依赖项。 旧 = 添加依赖项 - 当您右键单击项目中的 解决方案资源管理器并选择“添加依赖项”

我认为您的问题是您在一个项目中使用了一种方式,而在第二个项目中使用了另一种方式。

另一种可能性是一个项目是静态库。所以它不需要链接。

【讨论】:

参见此处:“如何:使用添加引用对话框添加或删除引用”(msdn.microsoft.com/en-us/library/wkze6zky(v=vs.110).aspx)

以上是关于C++ / VS 2012 - 多项目解决方案:一个项目中的链接器错误但另一个项目中没有的主要内容,如果未能解决你的问题,请参考以下文章

VS2012在一个解决方案中发布多个项目

谁能告诉我vs2012怎么用啊,完全不会用,想编写c++都找不到地方

C++ VS:多 DLL 解决方案中的“新建”和“删除”覆盖

vs2012警告未能加载包“visual c++ package”

在VS2012中C++嵌入python

包含 C++ 项目的 TFS 2010 源代码控制下的 VS2010 解决方案在打开时会发出警告