与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])
当你#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文件添加到您的项目中)并重新构建。你不应该在实践中需要这样做,但如果它消除了错误,那么至少它会揭示问题的根源。
这是一个奇怪的问题,GetItem()是由自动生成的.tli文件提供的内联函数。但编译器不会将其发送到.obj文件中。从'_variant_t'到T的隐含转换本身就是可怕的。 VS版本需要记录。 –