Reputation: 2838
I need to read entries from old-fashioned INI-file with a DLL and after some manipulation export them to VBA code.
The c++ code for the function looks like this:
BSTR __stdcall GetSectionEntry(LPCSTR sSection, LPCSTR sEntry)
{
LPCTSTR gszINIfilename = "C:\\test\\test.ini";
TCHAR localStr[64];
GetFileAttributes(gszINIfilename);
if (INVALID_FILE_ATTRIBUTES == GetFileAttributes(gszINIfilename) && GetLastError() == ERROR_FILE_NOT_FOUND) {
bstr_t bstrt = "";
return bstrt;
} else {
GetPrivateProfileStringA(sSection, sEntry, "", localStr, sizeof(localStr), gszINIfilename);
//_bstr_t bstrt(localStr);
CComBSTR bstrt(localStr);
return bstrt;
}
}
The VBA (Word 2016):
Declare PtrSafe Function GetSectionEntry Lib "test.dll" (ByVal sSection As String, ByVal sEntry As String) As String
For i = 0 To 5
Debug.Print ("Name = " & StrConv(GetSectionEntry("Name", CStr(i)), vbFromUnicode))
Next i
End finally the INI-file:
[Name]
0=123456789012345678901234567
1=1234567890123456789012345678
2=1234567890123456789012345678901234567890123456789012345678901
3=12345678901234567890123456789012345678901234567890123456789012
I compiled the DLL using VS2019 with either "Character Set" set to "Not Set" or to "Use Multi-Byte Character Set".
Debugging in VS shows that the strings are properly formatted (for example for 1 it's L"1234567890123456789012345678"). I tested it with different sizes of localStr (64..1024). I tried bstr_t and CComBSTR and a few more. In all cases print.debug in VBA shows following result:
Name = 123456789012345678901234567
Name = ?????????????? ????????????
Name = ??????????????????????????????1 ?? ??????????????yu ? rg|A ?
Name = 12345678901234567890123456789012345678901234567890123456789012
Any string that is longer than 27 and shorter than 62 characters is not properly encoded. When I checked them without StrConv(string, vbFromUnicode) they were missing all even null-characters. For that reason they are then encoded as some Asian characters:
The same happens for string that are 13--14 character long:
I'm very sure that I'm doing something trivial and stupid but I never had to write any C/C++ for windows. I would be grateful if anyone could point my mistake and correct me.
Upvotes: 0
Views: 176
Reputation: 58868
CComBSTR bstrt(localStr);
return bstrt;
This return statement converts the CComBSTR to a BSTR, and returns that, and then destroys the CComBSTR since it's no longer in scope. When the CComBSTR object is destroyed the string is freed.
Try return bstrt.Detach();
which detaches the string from the CComBSTR object so it won't be freed by the destructor.
After you return it, the string "belongs" to VBA and it's VBA's job to free it, which I assume it does automatically.
Upvotes: 1