Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. [Solved] QStrings from BSTR
QtWS25 Last Chance

[Solved] QStrings from BSTR

Scheduled Pinned Locked Moved General and Desktop
15 Posts 3 Posters 5.5k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • VRoninV Offline
    VRoninV Offline
    VRonin
    wrote on last edited by
    #1

    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

    "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
    ~Napoleon Bonaparte

    On a crusade to banish setIndexWidget() from the holy land of Qt

    1 Reply Last reply
    0
    • VRoninV Offline
      VRoninV Offline
      VRonin
      wrote on last edited by
      #2

      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();
      }
      @

      "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
      ~Napoleon Bonaparte

      On a crusade to banish setIndexWidget() from the holy land of Qt

      1 Reply Last reply
      0
      • N Offline
        N Offline
        NicuPopescu
        wrote on last edited by
        #3

        @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

        1 Reply Last reply
        0
        • VRoninV Offline
          VRoninV Offline
          VRonin
          wrote on last edited by
          #4

          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?

          "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
          ~Napoleon Bonaparte

          On a crusade to banish setIndexWidget() from the holy land of Qt

          1 Reply Last reply
          0
          • G Offline
            G Offline
            giesbert
            wrote on last edited by
            #5

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

            Nokia Certified Qt Specialist.
            Programming Is Like Sex: One mistake and you have to support it for the rest of your life. (Michael Sinz)

            1 Reply Last reply
            0
            • N Offline
              N Offline
              NicuPopescu
              wrote on last edited by
              #6

              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?

              1 Reply Last reply
              0
              • VRoninV Offline
                VRoninV Offline
                VRonin
                wrote on last edited by
                #7

                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

                "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
                ~Napoleon Bonaparte

                On a crusade to banish setIndexWidget() from the holy land of Qt

                1 Reply Last reply
                0
                • N Offline
                  N Offline
                  NicuPopescu
                  wrote on last edited by
                  #8

                  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!

                  1 Reply Last reply
                  0
                  • VRoninV Offline
                    VRoninV Offline
                    VRonin
                    wrote on last edited by
                    #9

                    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?

                    "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
                    ~Napoleon Bonaparte

                    On a crusade to banish setIndexWidget() from the holy land of Qt

                    1 Reply Last reply
                    0
                    • N Offline
                      N Offline
                      NicuPopescu
                      wrote on last edited by
                      #10

                      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

                      1 Reply Last reply
                      0
                      • VRoninV Offline
                        VRoninV Offline
                        VRonin
                        wrote on last edited by
                        #11

                        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!

                        "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
                        ~Napoleon Bonaparte

                        On a crusade to banish setIndexWidget() from the holy land of Qt

                        1 Reply Last reply
                        0
                        • N Offline
                          N Offline
                          NicuPopescu
                          wrote on last edited by
                          #12

                          @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?

                          1 Reply Last reply
                          0
                          • VRoninV Offline
                            VRoninV Offline
                            VRonin
                            wrote on last edited by
                            #13

                            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

                            "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
                            ~Napoleon Bonaparte

                            On a crusade to banish setIndexWidget() from the holy land of Qt

                            1 Reply Last reply
                            0
                            • N Offline
                              N Offline
                              NicuPopescu
                              wrote on last edited by
                              #14

                              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!

                              1 Reply Last reply
                              0
                              • VRoninV Offline
                                VRoninV Offline
                                VRonin
                                wrote on last edited by
                                #15

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

                                "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
                                ~Napoleon Bonaparte

                                On a crusade to banish setIndexWidget() from the holy land of Qt

                                1 Reply Last reply
                                0

                                • Login

                                • Login or register to search.
                                • First post
                                  Last post
                                0
                                • Categories
                                • Recent
                                • Tags
                                • Popular
                                • Users
                                • Groups
                                • Search
                                • Get Qt Extensions
                                • Unsolved