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. QString to C string -> Fortran
QtWS25 Last Chance

QString to C string -> Fortran

Scheduled Pinned Locked Moved Unsolved General and Desktop
13 Posts 8 Posters 1.1k 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.
  • G Offline
    G Offline
    gibbogle
    wrote on last edited by gibbogle
    #1

    I have a strange problem that may be created by my lack of C/C++ skills.

    Starting from QStrings, I create two C strings that are passed to a Fortran subroutine. On my Windows 7 machine this works fine - almost all the time. But on a colleagues Windows 10 machine the strings are corrupted every time.
    Here is the declaration of the Fortran subroutine, in a DLL:
    void execute(int *,char *, int *,char *, int *, int *);

    Here is the summary of what I'm doing in the Qt code:

    QString qsrt1, qstr2;
    char *cstr1, *cstr2;
    ...
    QByteArray ba = qstr1.toLocal8Bit();
    cstr1 = ba.data();
    ba = qstr2.toLocal8Bit();
    cstr2 = ba.data();
    ...
    execute(&ncpu,str1,&len1,str2,&len2,&res);

    The Fortran code is correct, but on one machine the strings str1 and str2 appear as non-printing characters - random memory, I suspect.
    What makes it very hard to debug is the fact that I almost never see the problem on my old W7 system; I thought it never happened, but then after running the program more than 20 times I got the corrupted string error. There is always the possibility that the problem is elsewhere in the Qt code, but I want to check that I'm not making a mistake with the string conversion. One question is whether I should be using const char * rather than char *.

    Thanks.

    K jeremy_kJ 2 Replies Last reply
    0
    • G gibbogle

      I have a strange problem that may be created by my lack of C/C++ skills.

      Starting from QStrings, I create two C strings that are passed to a Fortran subroutine. On my Windows 7 machine this works fine - almost all the time. But on a colleagues Windows 10 machine the strings are corrupted every time.
      Here is the declaration of the Fortran subroutine, in a DLL:
      void execute(int *,char *, int *,char *, int *, int *);

      Here is the summary of what I'm doing in the Qt code:

      QString qsrt1, qstr2;
      char *cstr1, *cstr2;
      ...
      QByteArray ba = qstr1.toLocal8Bit();
      cstr1 = ba.data();
      ba = qstr2.toLocal8Bit();
      cstr2 = ba.data();
      ...
      execute(&ncpu,str1,&len1,str2,&len2,&res);

      The Fortran code is correct, but on one machine the strings str1 and str2 appear as non-printing characters - random memory, I suspect.
      What makes it very hard to debug is the fact that I almost never see the problem on my old W7 system; I thought it never happened, but then after running the program more than 20 times I got the corrupted string error. There is always the possibility that the problem is elsewhere in the Qt code, but I want to check that I'm not making a mistake with the string conversion. One question is whether I should be using const char * rather than char *.

      Thanks.

      K Offline
      K Offline
      koahnig
      wrote on last edited by
      #2

      @gibbogle

      Make two different QByteArray one for each string and try

      Vote the answer(s) that helped you to solve your issue(s)

      G 2 Replies Last reply
      4
      • K koahnig

        @gibbogle

        Make two different QByteArray one for each string and try

        G Offline
        G Offline
        gibbogle
        wrote on last edited by
        #3

        @koahnig OK, will try. I have to transfer the executable to the colleague in a different time zone (8 hours different), so I will not know the result until she wakes up. Testing on my machine is useless.
        Thanks!

        1 Reply Last reply
        0
        • ad1170A Offline
          ad1170A Offline
          ad1170
          wrote on last edited by ad1170
          #4

          IMHO the safe way to do that can be:

          1. Convert the strings as you mentioned in your code above.
          2. Allocate memory for your string like below:
          char *str = new char[qbytearray.size()+1];
          strcpy(str, qbytearray.constData());
          
          1. Than call your Fortran function.
          2. Delete the allocated buffers after the Fortran function was executed (delete[] str).
          Christian EhrlicherC artwawA 2 Replies Last reply
          0
          • ad1170A ad1170

            IMHO the safe way to do that can be:

            1. Convert the strings as you mentioned in your code above.
            2. Allocate memory for your string like below:
            char *str = new char[qbytearray.size()+1];
            strcpy(str, qbytearray.constData());
            
            1. Than call your Fortran function.
            2. Delete the allocated buffers after the Fortran function was executed (delete[] str).
            Christian EhrlicherC Offline
            Christian EhrlicherC Offline
            Christian Ehrlicher
            Lifetime Qt Champion
            wrote on last edited by Christian Ehrlicher
            #5

            @ad1170 said in QString to C string -> Fortran:

            IMHO the safe way to do that can be:

            QByteArray is much better since you can't forget the deallocation...

            Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
            Visit the Qt Academy at https://academy.qt.io/catalog

            ad1170A 1 Reply Last reply
            4
            • ad1170A ad1170

              IMHO the safe way to do that can be:

              1. Convert the strings as you mentioned in your code above.
              2. Allocate memory for your string like below:
              char *str = new char[qbytearray.size()+1];
              strcpy(str, qbytearray.constData());
              
              1. Than call your Fortran function.
              2. Delete the allocated buffers after the Fortran function was executed (delete[] str).
              artwawA Offline
              artwawA Offline
              artwaw
              wrote on last edited by
              #6

              @ad1170 In addition to @Christian-Ehrlicher - you don't need +1 to the size() of QByteArray as this method already returns +1 for \0 char. And yes, QByteArray is much, much safer.

              For more information please re-read.

              Kind Regards,
              Artur

              JonBJ 1 Reply Last reply
              2
              • G gibbogle

                I have a strange problem that may be created by my lack of C/C++ skills.

                Starting from QStrings, I create two C strings that are passed to a Fortran subroutine. On my Windows 7 machine this works fine - almost all the time. But on a colleagues Windows 10 machine the strings are corrupted every time.
                Here is the declaration of the Fortran subroutine, in a DLL:
                void execute(int *,char *, int *,char *, int *, int *);

                Here is the summary of what I'm doing in the Qt code:

                QString qsrt1, qstr2;
                char *cstr1, *cstr2;
                ...
                QByteArray ba = qstr1.toLocal8Bit();
                cstr1 = ba.data();
                ba = qstr2.toLocal8Bit();
                cstr2 = ba.data();
                ...
                execute(&ncpu,str1,&len1,str2,&len2,&res);

                The Fortran code is correct, but on one machine the strings str1 and str2 appear as non-printing characters - random memory, I suspect.
                What makes it very hard to debug is the fact that I almost never see the problem on my old W7 system; I thought it never happened, but then after running the program more than 20 times I got the corrupted string error. There is always the possibility that the problem is elsewhere in the Qt code, but I want to check that I'm not making a mistake with the string conversion. One question is whether I should be using const char * rather than char *.

                Thanks.

                jeremy_kJ Offline
                jeremy_kJ Offline
                jeremy_k
                wrote on last edited by jeremy_k
                #7

                @gibbogle said in QString to C string -> Fortran:

                Starting from QStrings, I create two C strings that are passed to a Fortran subroutine. On my Windows 7 machine this works fine - almost all the time. But on a colleagues Windows 10 machine the strings are corrupted every time.
                Here is the declaration of the Fortran subroutine, in a DLL:
                void execute(int *,char *, int *,char *, int *, int *);

                Here is the summary of what I'm doing in the Qt code:

                QString qsrt1, qstr2;
                char *cstr1, *cstr2;
                ...
                QByteArray ba = qstr1.toLocal8Bit();

                QString::toLocal8Bit:

                If this string contains any characters that cannot be encoded in the locale, the returned byte array is undefined. Those characters may be suppressed or replaced by another.
                

                Do the locales or QString contents differ between the two machines?

                cstr1 = ba.data();
                ba = qstr2.toLocal8Bit();
                cstr2 = ba.data();
                ...
                execute(&ncpu,str1,&len1,str2,&len2,&res);
                

                QByteArray::data:

                The pointer remains valid as long as the byte array isn't reallocated or destroyed
                

                cstr1 becomes an unsafe pointer when ba is overwritten with the return value of qstr2.toLocal8Bit(). @koahnig's suggestion to use a QByteArray per QString should fix this.

                One question is whether I should be using const char * rather than char *.

                It's not a bad idea. There's also QByteArray::constData()

                Asking a question about code? http://eel.is/iso-c++/testcase/

                1 Reply Last reply
                3
                • artwawA artwaw

                  @ad1170 In addition to @Christian-Ehrlicher - you don't need +1 to the size() of QByteArray as this method already returns +1 for \0 char. And yes, QByteArray is much, much safer.

                  JonBJ Offline
                  JonBJ Offline
                  JonB
                  wrote on last edited by JonB
                  #8

                  @artwaw said in QString to C string -> Fortran:

                  @ad1170 In addition to @Christian-Ehrlicher - you don't need +1 to the size() of QByteArray as this method already returns +1 for \0 char.

                  Although I see @kshegunov & @SGaist have up-voted this, you're all wrong! :) You have to read https://doc.qt.io/qt-5/qbytearray.html#size carefully. Although it is true that QByteArray (usually) adds a \0 at the end of the byte array, it adds at index byteArray[byteArray.size()], i.e. 1 beyond the length returned by QByteArray::size():

                  The last byte in the byte array is at position size() - 1. In addition, QByteArray ensures that the byte at position size() is always '\0', so that you can use the return value of data() and constData() as arguments to functions that expect '\0'-terminated strings

                  QByteArray::size() returns the length without the extra terminating \0. That means that to copy it as a string you must indeed allocate char *str = new char[qbytearray.size()+1]; as @ad1170 did. If you don't do the + 1 then the strcpy() will copy the terminating \0 to 1 byte beyond the allocated area, leading to potential nasties...!

                  Christian EhrlicherC 1 Reply Last reply
                  4
                  • JonBJ JonB

                    @artwaw said in QString to C string -> Fortran:

                    @ad1170 In addition to @Christian-Ehrlicher - you don't need +1 to the size() of QByteArray as this method already returns +1 for \0 char.

                    Although I see @kshegunov & @SGaist have up-voted this, you're all wrong! :) You have to read https://doc.qt.io/qt-5/qbytearray.html#size carefully. Although it is true that QByteArray (usually) adds a \0 at the end of the byte array, it adds at index byteArray[byteArray.size()], i.e. 1 beyond the length returned by QByteArray::size():

                    The last byte in the byte array is at position size() - 1. In addition, QByteArray ensures that the byte at position size() is always '\0', so that you can use the return value of data() and constData() as arguments to functions that expect '\0'-terminated strings

                    QByteArray::size() returns the length without the extra terminating \0. That means that to copy it as a string you must indeed allocate char *str = new char[qbytearray.size()+1]; as @ad1170 did. If you don't do the + 1 then the strcpy() will copy the terminating \0 to 1 byte beyond the allocated area, leading to potential nasties...!

                    Christian EhrlicherC Offline
                    Christian EhrlicherC Offline
                    Christian Ehrlicher
                    Lifetime Qt Champion
                    wrote on last edited by
                    #9

                    @JonB You're right. For new/malloc and strcpy the additional \0 has to be considered.

                    Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
                    Visit the Qt Academy at https://academy.qt.io/catalog

                    1 Reply Last reply
                    3
                    • Christian EhrlicherC Christian Ehrlicher

                      @ad1170 said in QString to C string -> Fortran:

                      IMHO the safe way to do that can be:

                      QByteArray is much better since you can't forget the deallocation...

                      ad1170A Offline
                      ad1170A Offline
                      ad1170
                      wrote on last edited by ad1170
                      #10

                      @Christian-Ehrlicher said in QString to C string -> Fortran:

                      @ad1170 said in QString to C string -> Fortran:

                      IMHO the safe way to do that can be:
                      

                      QByteArray is much better since you can't forget the deallocation...

                      You are right. Inside Qt, use QByteArray or QString, no question.
                      But calling a function with an other language binding or from an other library which is awaiting char *str or const char *str i would prefer to make sure that the function gets what she wants. A plain C convention string with a trailing \0.

                      1 Reply Last reply
                      0
                      • Christian EhrlicherC Offline
                        Christian EhrlicherC Offline
                        Christian Ehrlicher
                        Lifetime Qt Champion
                        wrote on last edited by Christian Ehrlicher
                        #11

                        @ad1170 said in QString to C string -> Fortran:

                        But calling a function with an other language binding or from an other library which is awaiting char *str or const char *str i would prefer to make sure that the function gets what she wants.

                        It wantsa char*, it gets one - QByteArray::data() returns a pointer to a char array... it simply useless and error prone (e.g. forgot to call delete) what you suggest.

                        Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
                        Visit the Qt Academy at https://academy.qt.io/catalog

                        1 Reply Last reply
                        3
                        • K koahnig

                          @gibbogle

                          Make two different QByteArray one for each string and try

                          G Offline
                          G Offline
                          gibbogle
                          wrote on last edited by
                          #12

                          @koahnig According to my colleague, the program is now working - your fix was successful.. Thanks.

                          aha_1980A 1 Reply Last reply
                          2
                          • G gibbogle

                            @koahnig According to my colleague, the program is now working - your fix was successful.. Thanks.

                            aha_1980A Offline
                            aha_1980A Offline
                            aha_1980
                            Lifetime Qt Champion
                            wrote on last edited by
                            #13

                            Hi @gibbogle,

                            Glad to hear that. So please mark this topic as SOLVED too.

                            Thanks!

                            Qt has to stay free or it will die.

                            1 Reply Last reply
                            1

                            • Login

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