【发布时间】: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<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)
【问题讨论】:
-
奇怪的问题,GetItem()是自动生成的.tli文件提供的内联函数。但是编译器不会以某种方式将其发送到 .obj 文件中。从
_variant_t到 T 的隐含转换本身就是可疑的。 VS 版本需要记录。
标签: c++ com linker-errors lnk2019