[Solved] QStrings from BSTR



  • My problem is quite basic but I can't get it solved.
    I'm writing an application that interfaces with Excel and it passes string arguments as pointers to arrays of wchar_t (wchar_t**). The variable RawPathName below has this type.
    What I'm trying to do is to put those into a QString

    @
    QString Path=QString::fromWCharArray(*RawPathName);
    @

    but what I get back is just rubbish. The strange thing is that

    @
    QString Path=QString::fromWCharArray(L"C:\Temp");
    @

    works just fine so I cannot understand what is going wrong.
    Also

    @
    std::wstring TmpWstr=*RawPathName;
    QString Path=QString(std::string(TmpWstr.begin(),TmpWstr.end()).c_str());
    @

    Works fine (but obviously it's not safe if the string contains non ascii chars)

    Anybody has any Idea of what is going wrong?

    Thanks in advance



  • I also post the full code of my function

    @
    double __stdcall CLODiscountMargin(LPBSTR RawPathName){
    FolderPath=QString::fromWCharArray(*RawPathName);
    QString Filename=FolderPath+"\DataFile.dat";
    QFile file(Filename);
    if(!file.exists()){
    return 0.0;
    }
    if (!file.open(QIODevice::ReadOnly)){
    return 0.0;
    }
    QDataStream out(&file);
    out.setVersion(QDataStream::Qt_4_8);
    // Get things from file
    file.close();
    }
    @



  • @wchar_t* pathname = L"D:\Coolstream";
    wchar_t** RawPathName = &pathname;
    QString FolderPath=QString::fromWCharArray(*RawPathName);@

    this code works so I think your issue is elsewhere



  • Yes, even for me

    @ QString Path=QString::fromWCharArray(L"C:\Temp"); @

    works.
    I guess there is something more,

    @
    std::wstring TmpWstr=*RawPathName;
    QString Path=QString(std::string(TmpWstr.begin(),TmpWstr.end()).c_str());
    @

    when RawPathName contanins "C:\Temp", Path contains "C\ep" (only the chars with even index) any idea why this is happening?



  • Please take care that a BSTR is not a wchar_t!
    A BSTR contains the length of the string as first 2 bytes.



  • I have noticed the function's argument LPBSTR RawFolderPath is not even used ...

    try to check your code in a new simple project and btw what IDE do you use?



  • The different variable names are just a typo when I pasted the function here, it's much bigger than that and I wanted to focus only on the important part, now I corrected it.

    from http://msdn.microsoft.com/en-us/library/windows/desktop/ms221069(v=vs.85).aspx
    [quote] A BSTR is a pointer. The pointer points to the first character of the data string, not to the length prefix.[/quote]
    The fact that QString::fromWCharArray() works on BSTR is also proven by the fact that getting the string as a VARIANT (as I'm doing now as a workaround) and passing its bstrVal member, that is of type BSTR, to the aforementioned static method produces the right result



  • bq. typedef WCHAR OLECHAR;
    typedef OLECHAR* BSTR;
    typedef BSTR* LPBSTR;

    you asked firstly on wchar to QString and now you switch to BSTR to QString ... even BSTR is a typedef of WCHAR this doesn't mean they are handled the same way, the difference is not in the data type but in the content of the data array so that a BSTR is allocated by COM methods for COM methods ...

    so if you use outside COM methods both constructions:

    @BSTR MyBstr = L"C:\";
    BSTR MyBstr = SysAllocString(L"C:\");@

    will work with QString::fromWCharArray since, as you mentioned, it is a pointer to wchar

    but when passing to a COM method the first construction will fail the method as it expects a valid length prefix, and only the second one must be used ... I think there is no need of variants, for you BSTR should work

    hope it helps :)

    Cheers!



  • Probably I'm getting something wrong. I try correcting the function but with no result:

    @
    double __stdcall CLODiscountMargin(LPBSTR RawPathName){
    BSTR aBstring=SysAllocString(*RawPathName);
    FolderPath=QString::fromWCharArray(aBstring);
    QString Filename=FolderPath+"\DataFile.dat";
    QFile file(Filename);
    if(!file.exists()){
    return 0.0;
    }
    if (!file.open(QIODevice::ReadOnly)){
    return 0.0;
    }
    QDataStream out(&file);
    out.setVersion(QDataStream::Qt_4_8);
    // Get things from file
    file.close();
    SysFreeString(aBstring);
    }
    @

    Just a doubt, should I initialize the OLE ( OleInitialize(NULL) ) before running this function for it to work?



  • No, you don't need to initialize the COM library ... that function is an utility

    you use the function in a wrong way: just let your function as it was before and allocate a BSTR variable outside the function and pass it as &varname to it



  • the function CLODiscountMargin is an export of the library and is called directly from excel. Could you provide a basic example?
    Thanks a lot for your help!



  • @double __stdcall CLODiscountMargin(LPBSTR RawPathName){
    FolderPath=QString::fromWCharArray(*RawPathName);
    QString Filename=FolderPath+"\DataFile.dat";
    QFile file(Filename);
    if(!file.exists()){
    return 0.0;
    }
    if (!file.open(QIODevice::ReadOnly)){
    return 0.0;
    }
    QDataStream out(&file);
    out.setVersion(QDataStream::Qt_4_8);
    // Get things from file
    file.close();

    return 0.0;
    }@

    @BSTR aBstring=SysAllocString(L"C:\");//aBstring replaced by Excel's param
    CLODiscountMargin(&aBstring);
    @

    btw ... why do you return a double?



  • The thing is that I cannot do

    @
    CLODiscountMargin(&aBstring);
    @

    that function is an EXPORT of a dll, it is then imported in VBA with:

    @
    Declare Function CLODiscountMargin Lib "C:\Temp\MyAddin.dll" (aBstring As String) As Double
    @

    and called from an excel cell containing the formula =CLODiscountMargin("C:\Temp")

    This is also the reason why I return a double, the

    @
    // Get things from file
    @

    part search for a value in a file and returns it



  • bq. I’m writing an application that interfaces with Excel and it passes string arguments as pointers to arrays of wchar_t (wchar_t**)

    needless to mention once again that is an export function, while is your code having full access to it, and I think it's better from the beginning to make clear you are calling your library function from VBA, which I find it more appropriate than saying your app is interfacing with Excel which easily could mislead someone to believe Excel is used as ActiveX ...

    now ,I think you had not a good reading of how VBA pass string to dll's function: it is not anything magic, even VBA does help and converts everything for you ... please read this carefully "How To Pass a String Between Visual Basic and Your C DLL":http://support.microsoft.com/kb/187912

    so, the param in your lib's function is an either LPCSTR or C char* :

    bq. Because a BSTR variable is a pointer to a string, when Visual Basic passes it by reference it is actually passing a pointer to a pointer to a string. Most C functions simply expect a pointer to a string (such as LPSTR).

    concerning the return as double: tbh I don't understand where is the constraint: lib is your code and VBS is a script? is there some design decision involved?

    hope it helps!

    Cheers!



  • ok, LPCSTR* made it.
    Thanks a lot for your help!


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.