I have written a function in a C++ library that should take in a string from a given cell in Excel, then reverse the string, and return the reversed string. I used BSTR-to-stdstring and stdstring-to-BSTR found in this previously asked question (link: BSTR to std::string (std::wstring) and vice versa).
The error arises when I try to actually call the function from my .dll in Excel. For whatever reason, the .dll function does not appear to be properly returning a BSTR that Excel can display. When I input "test" into a cell and use the reverse_word function, I expect it to return "tset", but instead the function does not appear to return anything at all besides an empty string.
Here is my header file and .cpp code in Visual Studio for the .dll.
The header file:
#pragma once
#ifdef EXCELMATHLIB_EXPORTS
#define EXCELMATHLIB_API __declspec(dllexport)
#else
#define EXCELMATHLIB_API __declspec(dllimport)
#endif
extern "C" EXCELMATHLIB_API BSTR reverse_word(BSTR excelW);
The .cpp file:
BSTR WINAPI reverse_word(BSTR excelW)
{
std::string str = ConvertBSTRToMBS(excelW);
reverse(str.begin(), str.end());
return ConvertMBSToBSTR(str);
}
std::string ConvertBSTRToMBS(BSTR bstr)
//function found at: https://stackoverflow.com/questions/6284524/bstr-to-stdstring-stdwstring-and-vice-versa
{
int wslen = ::SysStringLen(bstr);
return ConvertWCSToMBS((wchar_t*)bstr, wslen);
}
std::string ConvertWCSToMBS(const wchar_t* pstr, long wslen)
//https://stackoverflow.com/questions/6284524/bstr-to-stdstring-stdwstring-and-vice-versa
{
int len = ::WideCharToMultiByte(CP_ACP, 0, pstr, wslen, NULL, 0, NULL, NULL);
std::string dblstr(len, '\0');
len = ::WideCharToMultiByte(CP_ACP, 0 /* no flags */,
pstr, wslen /* not necessary NULL-terminated */,
&dblstr[0], len,
NULL, NULL /* no default char */);
return dblstr;
}
BSTR ConvertMBSToBSTR(const std::string& str)
//online at https://stackoverflow.com/questions/6284524/bstr-to-stdstring-stdwstring-and-vice-versa
{
int wslen = ::MultiByteToWideChar(CP_ACP, 0 /* no flags */,
str.data(), str.length(),
NULL, 0);
BSTR wsdata = ::SysAllocStringLen(NULL, wslen);
::MultiByteToWideChar(CP_ACP, 0 /* no flags */,
str.data(), str.length(),
wsdata, wslen);
return wsdata;
}
This is my excel VBA module code:
Private Declare PtrSafe Function reverse_word_cpp _
Lib "C:\Users\artil\source\repos\ExcelMathLib\x64\Debug\ExcelMathLib.dll" Alias "reverse_word" _
(ByRef str As String) As String
Function reverse_word(word As String) 'reverse word wrapper function
Dim result As String
result = reverse_word_cpp(word)
MsgBox result
reverse_word = StrConv(result, vbFromUnicode)
End Function
I attempted to call the wrapper VBA function directly from a cell (i.e. =reverse_word(A1)
). A1 is a cell containing the text "test". The MsgBox result
and reverse_word = StrConv(result, vbFromUnicode)
both display empty messages/cells. I believe the issue is in my reverse_word_cpp
function.
I know that the ConvertMBSToBSTR
function does work, at least for a string written directly in C++.
return ConvertMBSToBSTR("test")
results in an output that function = StrConv(..., vbFromUnicode)
displays correctly in Excel.