Reputation: 994
I've written a c++ function in a DLL which exports a string to a VBA program:
BSTR _stdcall myFunc()
{
CRegKey Key;
CString sValue;
BSTR Str;
LONG nA = Key.Open(HKEY_LOCAL_MACHINE, _T("[group path goes here]"), KEY_READ);
ULONG nValueLength = 0;
LONG nB = Key.QueryStringValue(_T("[key I want to read goes here]"), NULL, &nValueLength);
if (nValueLength > 0)
{
LONG nC = Key.QueryStringValue(_T("[key I want to read goes here]"), sValue.GetBufferSetLength(nValueLength - 1), &nValueLength);
}
Str = _bstr_t(sValue.AllocSysString(), false);
return Str;
Now Str
is something like a version number: let's say "4.10.122".
If I call the function from VBA, I receive instead "4 . 1 0 . 1 2 2", where the "spaces" between each characters are NULL
(in VBA they are Chr(0)
).
I don't like the idea of having to use the Replace
function in my VBA code, so is there any way I can include that step in my c++ code?
EDIT: below the code I'm using to call the function in VBA:
Private Declare Function myFunc Lib "[Path of my DLL here]" () As String
Sub Return_string()
Dim a As String
a = myFunc()
End Sub
Upvotes: 0
Views: 872
Reputation: 1354
The problem stems from the Declare
statement. When interacting with such functions and strings in particular, VBA will always perform an implicit ANSI to Unicode conversion in both directions. In your case, VBA expects an ANSI string as the return value, which it can then expand into a Unicode equivalent.
To deal with this, you'll have to return an ANSI string and resort to SysAllocStringByteLen
:
CStringA sValueA(sValue);
Str = SysAllocStringByteLen(sValueA.GetBuffer(), sValueA.GetLength());
As an alternative, you may also embed a type library inside your DLL. This would omit the automatic string conversion.
Upvotes: 1
Reputation: 1167
Far from being able to help you with this specific need but curious about the subject, if i were to come up with a solution i would start from this answer https://stackoverflow.com/a/43423527/781933
According to the above mentioned @SimonMourier detailed answer, and further readings, you should consider string content encodings. The context of the DLL - VBA marshalling is to be considered and depends also on VBA function declaration (stated by @HansPassant).
From this MSDN documentation:
So if you use:
Private Declare Function myFunc Lib "[Path of my DLL here]" () As String
conversion from UNICODE to ANSI is needed via StrConv
Dim str As String
str = StrConv(myFunc(), vbFromUnicode)
Otherwise you should get rid of StrConv
but using DLL exported BSTR
with this declaration:
Private Declare Function myFunc Lib "[Path of my DLL here]" () As Variant
Upvotes: 1