COM未解析的外部符号

时间:2017-08-09 06:12:40

标签: c++ com linker-errors lnk2019

我正在编写一个小类来与通过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删除为a std::string

如果在main.cpp中我包含ExcelIO.h并构造一个xlWorksheet并调用getCell<type>(...);我收到链接错误。为什么我可以在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)

1 个答案:

答案 0 :(得分:0)

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

在项目目录中仔细检查以确保文件存在,并且Excel :: Range :: GetItem()函数同时存在。

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

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

...然后离开下面的专业化。此外,要么将专业化标记为&#34; inline&#34;或者将它移到完全在课堂内部。

如果这没有帮助,尝试编写一个简单的,常规的函数(不是模板专业化,而是一个函数)来完成你的专业版所做的 - 它返回一个字符串。首先尝试从main.cpp中调用 。你还得到链接错误。

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