La función DLL no funciona en un entorno VBA pero funciona en Excel VBA

 C Programming >> Programación C >  >> Tags >> Excel
La función DLL no funciona en un entorno VBA pero funciona en Excel VBA


Tengo la siguiente función contenida en una DLL que escribí (c++) que depuré en Excel y funcionó bien:


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;
}

Si FileName es por ejemplo foo_T024.lol , esta función devuelve correctamente un float (en C++, o Single en VBA) con el valor de 2.4 .


Llamo a la función desde VBA (tanto desde Excel como desde el otro entorno) como:


Private Declare Function ReturnT Lib "[myDLLname]" (ByVal FileName As String) As Single

Si hago lo mismo desde el otro entorno y uso la función en la misma cadena, obtengo un **ERROR** y lamentablemente nada más, porque no puedo depurar (siendo esta una aplicación propietaria).


¿Cuál podría ser el problema?


EDITAR:descubrí que este otro entorno es en realidad SAX, que es básicamente idéntico a VBA.


EDITAR:Logré vincular Visual Studio con la aplicación, para poder verificar qué se importó y qué está mal. FileName se ve correctamente importado (también usé un VARIANT -Introduzca el enfoque para ver si ese era el problema, que no lo era), pero recibo un error en esta línea:


wregex ToFind(L"_[tT]\\d{2,3}(\\_|\\.)");

El error es:



Y se detiene en xthrow.cpp en este punto:


#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 */

EDITAR:Mi versión de VS es 2013, el conjunto de herramientas de la plataforma es "Visual Studio 2013 - Windows XP (v120_xp)". La versión de mi compilador es:"Versión 18.00.21005.1 para x64"


Respuestas:


Resulta que algo estaba mal con la cadena que he estado importando. No entiendo qué, ya que cuando depuré el programa, se veían bien. Lo resolví importando un SAFEARRAY de cadenas (lo que me obligó a cambiar toda la función y el código VBA también), cuyo BSTR Se puede acceder al valor de la siguiente manera:


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);
}

Habiendo convertido todos los BSTR s en wstring s correctamente, podría trabajar con wregex s sin ningún problema.


Algunas respuestas de código


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);
}