【问题标题】:Unresolved External Symbol with COMCOM 无法解析的外部符号
【发布时间】:2018-01-16 21:09:18
【问题描述】:

我正在编写一个小类来与通过 COM 读取 excel 文件进行交互。到目前为止一切正常,除非我尝试读取单元格的值。

在测试期间,我最初从构造函数调用getCell() 只是为了检查它是否正常工作并且一切正常。一旦我开始从文件外部调用getCell(),我就会得到一个 LNK2019。

这是一个简短的示例:

ExcelIO.h

//MicroSoft Office Objects
#import "C:\Program Files (x86)\Common Files\Microsoft Shared\OFFICE14\mso.dll" \
rename("DocumentProperties", "DocumentPropertiesXL") \
rename("RGB", "RBGXL")

//Microsoft VBA Objects
#import "C:\Program Files (x86)\Common Files\Microsoft Shared\VBA\VBA6\VBE6EXT.OLB"

//Excel Application Objects
#import "C:\Program Files\Microsoft Office\Office14\EXCEL.EXE" \
rename("DialogBox", "DialogBoxXL") rename("RGB", "RBGXL") \
rename("DocumentProperties", "DocumentPropertiesXL") \
rename("ReplaceText", "ReplaceTextXL") \
rename("CopyFile", "CopyFileXL") \
exclude("IFont", "IPicture") no_dual_interfaces


class xlWorksheet {
public:
    xlWorksheet(Excel::_WorksheetPtr COMobjWs);

    template <class T>
    T getCell(int m, int n); // mth row, nth column
    template <>
    string getCell<string>(int m, int n);

private:
    Excel::_WorksheetPtr _COMobjWs {nullptr};
    Excel::RangePtr _usedRange {nullptr};
};


// TEMPLATE FUNCTION DEFINITIONS
template <class T>
T xlWorksheet::getCell(int m, int n) {
    T _temp;
    try {
        _temp = _usedRange->Item[m+1][n+1];
    }
    catch(...) {
        _temp = T {};
    }

    return _temp;
}


template <>
string xlWorksheet::getCell<string>(int m, int n) {
    // Get the _bstr_t value
    _bstr_t bstrt = getCell<_bstr_t>(m, n);

    // Detach the BSTR from the _bstr_t
    BSTR bstr = bstrt.Detach();

    // Initialize a blank string for the conversion (will be blank if conversion fails)
    string _temp;

    // Convert the BSTR into string
    int len = WideCharToMultiByte(CP_UTF8, 0, bstr, -1, NULL, 0, NULL, NULL);
    if (len > 0)
    {
        _temp.resize(len);
        WideCharToMultiByte(CP_UTF8, 0, bstr, -1, &_temp[0], len, NULL, NULL);
    }

    delete bstr;
    return _temp;
}

ExcelIO.cpp 中的 xlWorksheet 构造函数没有什么特别之处,它只是读取 COM 对象并分配私有变量。

您会注意到 getCell() 对于字符串有一个模板特化,因为 COM 喜欢返回 _bstr_t 类型,因此特化只是将 _bstr_t 剥离为 std::string

如果在 main.cpp 中包含 ExcelIO.h 并构造一个 xlWorksheet 并调用 getCell&lt;type&gt;(...); 我得到链接错误。为什么我可以在 ExcelIO 中完美调用它?

我遵循了类似的建议 here,但没有任何运气。

供参考,完整的错误是(使用双模板调用时):

LNK2019: unresolved external symbol "public: class _variant_t __thiscall Excel::Range::GetItem(class _variant_t const &,class _variant_t const &)" (?GetItem@Range@Excel@@QAE?AV_variant_t@@ABV3@0@Z) referenced in function "public: double __thiscall xlWorksheet::getCell<double>(int,int)" (??$getCell@N@xlWorksheet@@QAENHH@Z)

【问题讨论】:

  • 奇怪的问题,GetItem()是自动生成的.tli文件提供的内联函数。但是编译器不会以某种方式将其发送到 .obj 文件中。从_variant_t 到 T 的隐含转换本身就是可疑的。 VS 版本需要记录。

标签: c++ com linker-errors lnk2019


【解决方案1】:

当您#import dlls/OLB 文件时,它应该创建一对自动编译到您的项目中的文件——一个 .TLH 和一个 .TLI 文件。每次导入都应该有一对。 .TLH 是标头,.TLI 是实现。链接错误似乎表明您正在查找 .TLH,但由于某种原因,Visual Studio 未将 .TLI 编译到您的项目中。

仔细检查以确保文件在您的项目目录中,并且 Excel::Range::GetItem() 函数在两者中。

尝试从 xlWorkSheet 类声明中删除专用版本的 getCell 的空声明。也就是去掉这个位:

template <>
string getCell<string>(int m, int n);

...只留下下面的专业化。此外,要么将专业化标记为“内联”,要么将其完全移至类内部。

如果这没有帮助,请尝试编写一个简单的常规函数​​(不是模板特化,而是一个函数),它可以执行您的专用版本所做的事情——返回一个字符串。尝试首先从您的 main.cpp 调用 that。你是否仍然收到链接错误。

最后,如果 那个 没有帮助 - 并且假设 TLH/TLI 文件在那里并且函数在其中,那么手动尝试(仅用于测试)#include .TLI 文件您的 CPP 文件之一(或临时将 TLI 文件添加到您的项目中)并再次构建。您不应该永远在实践中需要这样做,但如果它消除了错误,那么至少它揭示了问题的根源。

【讨论】:

    猜你喜欢
    • 2018-07-01
    • 2018-02-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-09
    • 2011-03-21
    • 2019-01-14
    • 2012-07-10
    相关资源
    最近更新 更多