DLL関数がVBA環境では動作せず、Excel VBAでは動作する



私が作成した DLL (c++) に含まれる次の関数を Excel でデバッグしたところ、問題なく動作しました:


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 です 、この関数は正しく float を返します (C++ の場合、または Single 2.4 の値を持つ .


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}(\\_|\\.)");

エラー:



そして 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」


答え:


インポートした文字列に問題があることがわかりました。私がプログラムをデバッグしたとき、それらは問題なく見えたので、私は何を理解していません。 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);
}

すべての BSTR を変換した後 wstring の その通りです。wregex で作業できます 問題ありません。


いくつかのコードの回答


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;
}
Private Declare Function ReturnT Lib "[myDLLname]" (ByVal FileName As String) As Single 
wregex ToFind(L"_[tT]\\d{2,3}(\\_|\\.)");
#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 */
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);
}