与COM无法解析的外部符号

问题描述:

我正在写一个小班来通过COM读取excel文件的接口。到目前为止,一切都很好,除非我试图读取单元格的值。与COM无法解析的外部符号

在测试过程中,我最初从构造函数调用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<type>(...);我收到链接错误。为什么当我可以从ExcelIO内部完美地调用它时呢?

我按照建议here这是相似的,但没有任何运气。

作为参考,完全错误的是(以双模板调用时):

LNK2019: unresolved external symbol "public: class _variant_t __thiscall Excel::Range::GetItem(class _variant_t const &,class _variant_t const &)" ([email protected]@[email protected]@[email protected]@[email protected]@Z) referenced in function "public: double __thiscall xlWorksheet::getCell<double>(int,int)" ([email protected]@[email protected]@[email protected]) 
+0

这是一个奇怪的问题,GetItem()是由自动生成的.tli文件提供的内联函数。但编译器不会将其发送到.obj文件中。从'_variant_t'到T的隐含转换本身就是可怕的。 VS版本需要记录。 –

当你#IMPORT的dll文件/文件OLB,它应该创建一个对文件自动被编译到项目 - .TLH和.TLI文件。每个导入应该有一对这样的。 .TLH是标题,.TLI是实现。链接错误似乎表明您正在查找.TLH,但由于某些原因,Visual Studio不会将.TLI编译到您的项目中。

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

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

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

...并且就在下面的专业化。此外,要么将专业化标记为“内联”,要么将其完全移至课堂内部。

如果这没有帮助,请尝试编写一个简单的常规函数​​(不是模板专门化函数,而是一个函数),它可以执行您的专用版本所做的工作 - 它会返回一个字符串。请尝试从您的main.cpp中首先呼叫。你仍然有链接错误。

最后,如果不起作用 - 并假设TLH/TLI文件存在并且函数位于它们中,则手动尝试(仅用于测试)#包括您的CPP中的.TLI文件文件(或临时将TLI文件添加到您的项目中)并重新构建。你不应该在实践中需要这样做,但如果它消除了错误,那么至少它会揭示问题的根源。