Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. C / C++ / MFC
  4. Translating C# structure to C++

Translating C# structure to C++

Scheduled Pinned Locked Moved C / C++ / MFC
csharpc++question
7 Posts 4 Posters 0 Views 1 Watching
  • 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.
  • _ Offline
    _ Offline
    __DanC__
    wrote on last edited by
    #1

    I have a structure in C# which is read using a BinaryReader like so:

    binaryReader.ReadInt32();
    binaryReader.ReadInt32();
    binaryReader.ReadString();
    binaryReader.ReadString();

    I need to be able to send this structure from a C++ app, I have managed to send across the two ints and I realise that the strings have a length marker in front of them but I cannot get it to send the string. I am currently using a struct like this:

    struct MyData
    {
    int val1;
    int val2;
    int strLength1;
    LPCTSTR string1;
    int strLength2;
    LPCTSTR string2;
    };

    This send the ints fine but I get 2 0 length strings. What am I doing wrong?

    M L 2 Replies Last reply
    0
    • _ __DanC__

      I have a structure in C# which is read using a BinaryReader like so:

      binaryReader.ReadInt32();
      binaryReader.ReadInt32();
      binaryReader.ReadString();
      binaryReader.ReadString();

      I need to be able to send this structure from a C++ app, I have managed to send across the two ints and I realise that the strings have a length marker in front of them but I cannot get it to send the string. I am currently using a struct like this:

      struct MyData
      {
      int val1;
      int val2;
      int strLength1;
      LPCTSTR string1;
      int strLength2;
      LPCTSTR string2;
      };

      This send the ints fine but I get 2 0 length strings. What am I doing wrong?

      L Offline
      L Offline
      Luc Pattyn
      wrote on last edited by
      #2

      One way that works AFAIK is using fixed-length strings, put them in length+chararray on the C/C++ side and in length+array on the managed side, using some Marshal attribute to indicate that the array data has to be there, not just a reference. It is something like [MarshalAs(UnmanagedType.ByValArray, SizeConst=16)] BTW: as always, be wary of different character types. :)

      Luc Pattyn [Forum Guidelines] [My Articles]


      Voting for dummies? No thanks. X|


      1 Reply Last reply
      0
      • _ __DanC__

        I have a structure in C# which is read using a BinaryReader like so:

        binaryReader.ReadInt32();
        binaryReader.ReadInt32();
        binaryReader.ReadString();
        binaryReader.ReadString();

        I need to be able to send this structure from a C++ app, I have managed to send across the two ints and I realise that the strings have a length marker in front of them but I cannot get it to send the string. I am currently using a struct like this:

        struct MyData
        {
        int val1;
        int val2;
        int strLength1;
        LPCTSTR string1;
        int strLength2;
        LPCTSTR string2;
        };

        This send the ints fine but I get 2 0 length strings. What am I doing wrong?

        M Offline
        M Offline
        Matthew Faithfull
        wrote on last edited by
        #3

        At a guess I'd day you need two shorts for your string lengths or possibly even two BYTEs. If C# strings are a development of BSTRs then I doubt the string lengths will be as much as the 4 bytes you get with an int. 4GB long strings are really not what MS want to be supporting I guess. The other thing is you need the character data itself effectively in the structure rather than pointers to the characters (LPCTSTR). You want something like this. struct MyData { int val1; int val2; unsigned short strLength1; TCHAR string1[strLength1]; unsigned short strLength2; TCHAR string2[strLength2]; }; but of course you can't do that directly as strLength1 and strLength2 are not known at compile time. This means you're likely going to have to use some form of serialization/deserilaization rather then just passing a structure unless you can use fixed length strings.

        "The secret of happiness is freedom, and the secret of freedom, courage." Thucydides (B.C. 460-400)

        _ 1 Reply Last reply
        0
        • M Matthew Faithfull

          At a guess I'd day you need two shorts for your string lengths or possibly even two BYTEs. If C# strings are a development of BSTRs then I doubt the string lengths will be as much as the 4 bytes you get with an int. 4GB long strings are really not what MS want to be supporting I guess. The other thing is you need the character data itself effectively in the structure rather than pointers to the characters (LPCTSTR). You want something like this. struct MyData { int val1; int val2; unsigned short strLength1; TCHAR string1[strLength1]; unsigned short strLength2; TCHAR string2[strLength2]; }; but of course you can't do that directly as strLength1 and strLength2 are not known at compile time. This means you're likely going to have to use some form of serialization/deserilaization rather then just passing a structure unless you can use fixed length strings.

          "The secret of happiness is freedom, and the secret of freedom, courage." Thucydides (B.C. 460-400)

          _ Offline
          _ Offline
          __DanC__
          wrote on last edited by
          #4

          Thanks, I thought I would end up doing some serialization. I have checked the BinaryWriter documentation and it states

          This method first writes the length of the string as a four-byte unsigned integer, and then writes that many characters to the stream. This method writes a length-prefixed string to this stream using the BinaryWriter instance's current Encoding.

          So it seems it does need a 4-bytes uint to prefix the length. So my next question is how would I create a byte array containing the strings and the lengths? (C++ is not my strong point!), I know how to create the array using malloc and copy the strings in but not the ints.

          M 1 Reply Last reply
          0
          • _ __DanC__

            Thanks, I thought I would end up doing some serialization. I have checked the BinaryWriter documentation and it states

            This method first writes the length of the string as a four-byte unsigned integer, and then writes that many characters to the stream. This method writes a length-prefixed string to this stream using the BinaryWriter instance's current Encoding.

            So it seems it does need a 4-bytes uint to prefix the length. So my next question is how would I create a byte array containing the strings and the lengths? (C++ is not my strong point!), I know how to create the array using malloc and copy the strings in but not the ints.

            M Offline
            M Offline
            Matthew Faithfull
            wrote on last edited by
            #5

            Yep, I'd say a malloc, or more properly, BYTE* pBuffer = new BYTE[uBufferSize]; is the way to go. Once you've got your buffer you write the strings in by casting a copy of pBuffer + n to a TCHAR* and copy your ints in by casting pBuffer + n to an int* and setting its value. int* pFirstInt = reinterpret_cast<int*>(pBuffer + 0); *pFirstInt = nValue; int* pSecondInt = reinterpret_cast<int*>(pBuffer + 4); *SecondInt = nValue2; It's not pretty but then this sort of stuff seldom is. You could create some struct types and cast to those. Up to you really. There are almost certainly fancier ways to do this with operator << overloading and stl string stream modifiers but I wouldn't go there unless you've got a lot of complex data to transfer and you know your stl.

            "The secret of happiness is freedom, and the secret of freedom, courage." Thucydides (B.C. 460-400)

            _ 1 Reply Last reply
            0
            • M Matthew Faithfull

              Yep, I'd say a malloc, or more properly, BYTE* pBuffer = new BYTE[uBufferSize]; is the way to go. Once you've got your buffer you write the strings in by casting a copy of pBuffer + n to a TCHAR* and copy your ints in by casting pBuffer + n to an int* and setting its value. int* pFirstInt = reinterpret_cast<int*>(pBuffer + 0); *pFirstInt = nValue; int* pSecondInt = reinterpret_cast<int*>(pBuffer + 4); *SecondInt = nValue2; It's not pretty but then this sort of stuff seldom is. You could create some struct types and cast to those. Up to you really. There are almost certainly fancier ways to do this with operator << overloading and stl string stream modifiers but I wouldn't go there unless you've got a lot of complex data to transfer and you know your stl.

              "The secret of happiness is freedom, and the secret of freedom, courage." Thucydides (B.C. 460-400)

              _ Offline
              _ Offline
              __DanC__
              wrote on last edited by
              #6

              Thanks for the tip, that worked for the ints perfectly but still not getting the strings. My code now is:

              int* pFirstValue = reinterpret_cast<int*>(pBuffer + 0); // First integer
              int* pSecondValue = reinterpret_cast<int*>(pBuffer + 4); // Second integer
              unsigned int* pStringLength1 = reinterpret_cast(pBuffer + 8); // First string length marker
              unsigned int* pStringLength2 = reinterpret_cast(pBuffer + 12 + (sizeof(WCHAR) * firststring)); // Second string length marker

              *pFirstValue = 1;
              *pSecondValue = 2;
              *pStringLength1 = strlen(firststring);
              *pStringLength2 = strlen(secondstring);

              strcpy((char*)(pBuffer + 12), firststring);
              strcpy((char*)(pBuffer + 16 + (sizeof(WCHAR) * firststring)), secondstring);

              That appears to me to be correct but as I've said before, C++ is not my strong point. Does that look correct?

              M 1 Reply Last reply
              0
              • _ __DanC__

                Thanks for the tip, that worked for the ints perfectly but still not getting the strings. My code now is:

                int* pFirstValue = reinterpret_cast<int*>(pBuffer + 0); // First integer
                int* pSecondValue = reinterpret_cast<int*>(pBuffer + 4); // Second integer
                unsigned int* pStringLength1 = reinterpret_cast(pBuffer + 8); // First string length marker
                unsigned int* pStringLength2 = reinterpret_cast(pBuffer + 12 + (sizeof(WCHAR) * firststring)); // Second string length marker

                *pFirstValue = 1;
                *pSecondValue = 2;
                *pStringLength1 = strlen(firststring);
                *pStringLength2 = strlen(secondstring);

                strcpy((char*)(pBuffer + 12), firststring);
                strcpy((char*)(pBuffer + 16 + (sizeof(WCHAR) * firststring)), secondstring);

                That appears to me to be correct but as I've said before, C++ is not my strong point. Does that look correct?

                M Offline
                M Offline
                Mark Salsbery
                wrote on last edited by
                #7

                This won't solve your marshaling problem, but: You can't use strcpy, or TCHAR. All your strings are wchar_t in C# so you should be using only wide character functions and types. Mark

                Mark Salsbery Microsoft MVP - Visual C++ :java:

                1 Reply Last reply
                0
                Reply
                • Reply as topic
                Log in to reply
                • Oldest to Newest
                • Newest to Oldest
                • Most Votes


                • Login

                • Don't have an account? Register

                • Login or register to search.
                • First post
                  Last post
                0
                • Categories
                • Recent
                • Tags
                • Popular
                • World
                • Users
                • Groups