【发布时间】:2017-10-09 00:22:29
【问题描述】:
我在 Excel 中调试的 (c++) 编写的 DLL 中包含以下函数,并且工作正常:
float _stdcall ReturnT(LPCSTR FileName)
{
// Extracts the generic language string from the (importing BSTR
// would import kanji or whatever) and converts it into a wstring
wstring str = CA2T(FileName);
// Sets the string to find as _t or _T followed by 2 or 3 digits and a subsequent _ or .
wregex ToFind(L"_[tT]\\d{2,3}(_|.)");
wsmatch TStr;
regex_search(str, TStr, ToFind); // Now the wsmatch variable contains all the info about the matching
wstring T = TStr.str(0).erase(0, 2); // Removes the first 2 characters
T.erase(T.end() - 1); // Removes the last character
// Checks if T is 3 digits or not (2 digits) and eventually add a "."
wstring TVal = L"";
if (T.size() == 3)
{
TVal += T.substr(0, 2) + L"." + T.substr(2, 3);
}
else if (T.size() == 2)
{
TVal += T;
}
// Converts T string to a float
const float TValue = (float) _wtof(TVal.c_str());
return TValue;
}
如果FileName 是例如foo_T024.lol,则此函数正确返回值为2.4 的float(在C++ 中,或在VBA 中Single)。
我从 VBA(Excel 和其他环境)调用函数为:
Private Declare Function ReturnT Lib "[myDLLname]" (ByVal FileName As String) As Single
如果我在其他环境中执行相同操作并在同一个字符串上使用该函数,我会得到一个**ERROR**,遗憾的是没有别的,因为我无法调试(这是一个专有应用程序)。
可能是什么问题?
编辑:我发现这个其他环境实际上是SAX,它与VBA基本相同。
编辑:我设法将 Visual Studio 与应用程序链接起来,这样我就可以检查导入的内容和问题所在。 FileName 看起来正确导入,(我还使用了 VARIANT-input 方法来查看是否是问题所在,但事实并非如此)但我在这一行收到错误:
wregex ToFind(L"_[tT]\\d{2,3}(\\_|\\.)");
错误是:
NSI2000.exe 中 0x75F0C54F 处未处理的异常:Microsoft C++ 异常:内存位置 0x0018E294 处的 std::regex_error。
此时它停在xthrow.cpp:
#if _HAS_EXCEPTIONS
#include <regex>
_STD_BEGIN
_CRTIMP2_PURE _NO_RETURN(__CLRCALL_PURE_OR_CDECL _Xregex_error(regex_constants::error_type _Code))
{ // report a regex_error
_THROW_NCEE(regex_error, _Code);
} <--- Code stops here
_STD_END
#endif /* _HAS_EXCEPTIONS */
编辑:我的 VS 版本是 2013,平台工具集是“Visual Studio 2013 - Windows XP (v120_xp)”。我的编译器版本是:“版本 18.00.21005.1 for x64”
【问题讨论】:
-
该功能是否已在系统中注册?
-
不,显然不需要。该函数在其他函数的同一个
extern "C"块中定义,似乎工作得很好。 -
您是否尝试注册它以查看它是否解决了问题?它可以是在 Excel 中作为 IDE 的一部分加载的任意 .dll,但不会在您的其他应用程序中加载。
-
有什么原因你不说“其他环境”是什么?
-
这段代码深受“失败不是一种选择”的影响。无法告诉调用者文件名无法转换为浮点数。如果没有正则表达式匹配,它肯定会以非常讨厌和无法诊断的方式失败。就像“其他环境”通过 BSTR 而不是 LPCSTR(字符串的正常编组)时一样。尽管它不太可能因 std::regex_error 异常而爆炸,但您必须发布堆栈跟踪以获得更好的猜测。并记录VS版本,早期的有很多正则表达式错误。