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

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 gibbogle
    9 Oct 2020, 13:40

    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 9 Oct 2020, 13:57 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 9 Oct 2020, 14:08
    4
    • K koahnig
      9 Oct 2020, 13:57

      @gibbogle

      Make two different QByteArray one for each string and try

      G Offline
      G Offline
      gibbogle
      wrote on 9 Oct 2020, 14:08 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
      • A Offline
        A Offline
        ad1170
        wrote on 9 Oct 2020, 16:21 last edited by ad1170 10 Sept 2020, 16:23
        #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).
        C A 2 Replies Last reply 9 Oct 2020, 16:27
        0
        • A ad1170
          9 Oct 2020, 16:21

          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).
          C Offline
          C Offline
          Christian Ehrlicher
          Lifetime Qt Champion
          wrote on 9 Oct 2020, 16:27 last edited by Christian Ehrlicher 10 Sept 2020, 16:28
          #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

          A 1 Reply Last reply 10 Oct 2020, 09:13
          4
          • A ad1170
            9 Oct 2020, 16:21

            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).
            A Offline
            A Offline
            artwaw
            wrote on 9 Oct 2020, 16:52 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

            J 1 Reply Last reply 10 Oct 2020, 08:41
            2
            • G gibbogle
              9 Oct 2020, 13:40

              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.

              J Offline
              J Offline
              jeremy_k
              wrote on 10 Oct 2020, 05:05 last edited by jeremy_k 10 Oct 2020, 05:06
              #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
              • A artwaw
                9 Oct 2020, 16:52

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

                J Offline
                J Offline
                JonB
                wrote on 10 Oct 2020, 08:41 last edited by JonB 10 Oct 2020, 08:44
                #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...!

                C 1 Reply Last reply 10 Oct 2020, 08:51
                4
                • J JonB
                  10 Oct 2020, 08:41

                  @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...!

                  C Offline
                  C Offline
                  Christian Ehrlicher
                  Lifetime Qt Champion
                  wrote on 10 Oct 2020, 08:51 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
                  • C Christian Ehrlicher
                    9 Oct 2020, 16:27

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

                    A Offline
                    A Offline
                    ad1170
                    wrote on 10 Oct 2020, 09:13 last edited by ad1170 10 Oct 2020, 09:14
                    #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
                    • C Offline
                      C Offline
                      Christian Ehrlicher
                      Lifetime Qt Champion
                      wrote on 10 Oct 2020, 11:58 last edited by Christian Ehrlicher 10 Oct 2020, 11:59
                      #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
                        9 Oct 2020, 13:57

                        @gibbogle

                        Make two different QByteArray one for each string and try

                        G Offline
                        G Offline
                        gibbogle
                        wrote on 12 Oct 2020, 19:26 last edited by
                        #12

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

                        A 1 Reply Last reply 13 Oct 2020, 15:00
                        2
                        • G gibbogle
                          12 Oct 2020, 19:26

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

                          A Offline
                          A Offline
                          aha_1980
                          Lifetime Qt Champion
                          wrote on 13 Oct 2020, 15:00 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

                          11/13

                          10 Oct 2020, 11:58

                          • Login

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