【问题标题】:DLL function not working in a VBA environment but working in Excel VBADLL 函数不在 VBA 环境中工作,但在 Excel VBA 中工作
【发布时间】: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版本,早期的有很多正则表达式错误。

标签: c++ excel string vba


【解决方案1】:

原来我导入的字符串有问题。我不明白什么,因为当我调试程序时,它们看起来很好。我通过导入字符串的SAFEARRAY 来解决(这需要我更改整个函数和VBA 代码),其BSTR 值可以按如下方式访问:

int _stdcall FilenameSort(LPSAFEARRAY* StringArray)
{
    // Fills a vector with the wstring values
    char** StrPtr = 0;
    long LowerBound = 0;  SafeArrayGetLBound(*StringArray, 1, &LowerBound);
    long UpperBound = 0;  SafeArrayGetUBound(*StringArray, 1, &UpperBound);
    const long Dimension = UpperBound - LowerBound;
    SafeArrayAccessData(*StringArray, reinterpret_cast<void**>(&StrPtr));

    BSTR element;
    vector<wstring> wstrArr;

    for (long i = 0; i <= Dimension; ++i)
    {
        SafeArrayGetElement(*StringArray, &i, &element);
        wstring ws(element, SysStringLen(element));
        wstrArr.push_back(ws);
    }

正确转换wstrings 中的所有BSTRs 后,我可以毫无问题地使用wregexs。

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-03-03
  • 2016-11-25
  • 2016-07-04
相关资源
最近更新 更多