Search code examples
c++stringvbacharbstr

Remove chr(0) from (c++ BSTR) string in VBA


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

Solution

  • 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

    Update

    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:

    • When a VBA user-defined function is declared as taking a String argument, Excel converts the supplied string to a byte-string in a locale-specific way.
    • If you want your function to be passed a Unicode string, your VBA user-defined function should accept a Variant instead of a String argument.

    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