marshal binary data file, written with C++, with my C# code

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Vertilka

    marshal binary data file, written with C++, with my C# code

    I need to read binary data file written by C++ program, using my C#
    application.
    How do i marshal the bytes i read with my C# code to .NET types.

    The data is numbers (integers float doubles etc..) and strings.

    I looked at the Marshal class but did not know how to use it with file.
    Please add few code lines.

    Thanks alot

  • bb

    #2
    Re: marshal binary data file, written with C++, with my C# code

    here is something i use for reading a string stored by C++ as an IntPtr


    public class MarshalUtil
    {
    IntPtr m_objData = IntPtr.Zero;
    int m_nPosition = 0;

    public MarshalUtil(Int Ptr objData)
    {
    m_objData = objData;
    }

    public string ReadString()
    {
    ArrayList objBytes = new ArrayList();
    byte byt;
    string strData = "";

    while((byt = Marshal.ReadByt e(m_objData, m_nPosition)) != 0)
    {
    strData += (char) byt;
    m_nPosition += 2;
    }

    m_nPosition += 2;

    return strData;
    }

    public bool MoreData
    {
    get
    {
    return (Marshal.ReadBy te(m_objData, m_nPosition) != 0);
    }
    }
    }

    Comment

    • Vertilka

      #3
      Re: marshal binary data file, written with C++, with my C# code

      Thanks bb,

      And what about integers float and doubles, how to marshal them ?

      :)

      Comment

      • Jon Skeet [C# MVP]

        #4
        Re: marshal binary data file, written with C++, with my C# code

        bb wrote:[color=blue]
        > here is something i use for reading a string stored by C++ as an IntPtr
        >
        > public class MarshalUtil
        > {
        > IntPtr m_objData = IntPtr.Zero;
        > int m_nPosition = 0;
        >
        > public MarshalUtil(Int Ptr objData)
        > {
        > m_objData = objData;
        > }
        >
        > public string ReadString()
        > {
        > ArrayList objBytes = new ArrayList();
        > byte byt;
        > string strData = "";
        >
        > while((byt = Marshal.ReadByt e(m_objData, m_nPosition)) != 0)
        > {
        > strData += (char) byt;
        > m_nPosition += 2;
        > }
        >
        > m_nPosition += 2;
        >
        > return strData;
        > }[/color]

        That will be hideously inefficient with large strings - you should at
        the very least be using a StringBuilder. You also seem to be ignoring
        every other byte - I don't believe the above will work with strings
        containing Unicode characters above U+00FF. Instead, you should read
        *two* bytes, and shift one left by 8 bits.

        Jon

        Comment

        • Jon Skeet [C# MVP]

          #5
          Re: marshal binary data file, written with C++, with my C# code

          Vertilka wrote:[color=blue]
          > And what about integers float and doubles, how to marshal them ?[/color]

          Have a look at Marshal.ReadInt 32 (etc) for integers. For doubles you
          should use Marshal.ReadInt 64 and then call
          BitConverter.In t64BitsToDouble . I'm not guaranteeing it will work, but
          it's certainly worth a try.

          Unfortunately there's no direct equivalent for that process for floats
          (at least not in 1.1 - I haven't checked 2.0) - instead you'd probably
          want to use BitConverter.To Single(byte[]) having read 4 bytes into a
          byte array first.

          Jon

          Comment

          • Nicholas Paldino [.NET/C# MVP]

            #6
            Re: marshal binary data file, written with C++, with my C# code

            You can always use the overload of the static Copy method which takes an
            IntPtr and populates an array of doubles (or floats, there is an overload
            for that as well). If you want one double/float, you can just declare an
            array of one element (a little overkill, I know, but less code, right?).

            Also, if the OP is willing to use unsafe code, then it could be much
            easier (just cast to the appropriate pointer type and dereference).


            --
            - Nicholas Paldino [.NET/C# MVP]
            - mvp@spam.guard. caspershouse.co m

            "Jon Skeet [C# MVP]" <skeet@pobox.co m> wrote in message
            news:1137675274 .455883.8610@g4 4g2000cwa.googl egroups.com...[color=blue]
            > Vertilka wrote:[color=green]
            >> And what about integers float and doubles, how to marshal them ?[/color]
            >
            > Have a look at Marshal.ReadInt 32 (etc) for integers. For doubles you
            > should use Marshal.ReadInt 64 and then call
            > BitConverter.In t64BitsToDouble . I'm not guaranteeing it will work, but
            > it's certainly worth a try.
            >
            > Unfortunately there's no direct equivalent for that process for floats
            > (at least not in 1.1 - I haven't checked 2.0) - instead you'd probably
            > want to use BitConverter.To Single(byte[]) having read 4 bytes into a
            > byte array first.
            >
            > Jon
            >[/color]


            Comment

            • Vertilka

              #7
              Re: marshal binary data file, written with C++, with my C# code

              Jon, Nicholas,
              Thanks for your answers.

              Can you both post code snippets.
              Lets say that i have 8 bytes that i want to get a bouble from them.

              Thanks.

              Comment

              • bb

                #8
                Re: marshal binary data file, written with C++, with my C# code

                yes its just used to get a known small length string from my device
                driver

                although im not sure thats an excuse for hideous code ;-)

                Comment

                • Vertilka

                  #9
                  Re: marshal binary data file, written with C++, with my C# code

                  Jon,

                  I tried you advise.
                  How do i convert array of bytes to IntPtr, to use with
                  Marshal.ReadInt 32 ?

                  === Code snippet ===

                  FileStream fs = new FileStream(@"C: \myfile.bin", FileMode.Open);

                  byte[] buffer = new byte[1024];
                  fs.Read(buffer, 0, 8);

                  Marshal.ReadInt 64( ???? );

                  ??? BitConverter.In t64BitsToDouble ();

                  === Code snippet ===

                  Comment

                  • Willy Denoyette [MVP]

                    #10
                    Re: marshal binary data file, written with C++, with my C# code


                    "Vertilka" <vertilka@gmail .com> wrote in message
                    news:1137683565 .065831.198970@ g44g2000cwa.goo glegroups.com.. .
                    | Jon,
                    |
                    | I tried you advise.
                    | How do i convert array of bytes to IntPtr, to use with
                    | Marshal.ReadInt 32 ?
                    |
                    | === Code snippet ===
                    |
                    | FileStream fs = new FileStream(@"C: \myfile.bin", FileMode.Open);
                    |
                    | byte[] buffer = new byte[1024];
                    | fs.Read(buffer, 0, 8);
                    |
                    | Marshal.ReadInt 64( ???? );
                    |
                    | ??? BitConverter.In t64BitsToDouble ();
                    |
                    | === Code snippet ===
                    |

                    Use the BinaryReader and wrap your FileStream, there is no need to call
                    Marshal methods, you simply need to call the right read method. Just beware
                    of the char encoding when reading cjar array's and strings.


                    string s1;
                    byte b1;
                    int i1;
                    float f1;
                    double d1;
                    char[] ca;

                    ....
                    using(BinaryRea der binReader =
                    new BinaryReader(Fi le.Open(@".\myf ile.bin", FileMode.Open)) )
                    {
                    try {
                    while (true)
                    {
                    s1 = binReader.ReadS tring();
                    b1 = binReader.ReadB yte();
                    i1 = binReader.ReadI nt32();
                    f1 = binReader.ReadS ingle();
                    d1 = binReader.ReadD ouble();
                    ca = binReader.ReadC hars(5);
                    Console.WriteLi ne(f1);
                    }
                    }
                    catch(EndOfStre amException ex)
                    {
                    // end of file reached
                    }
                    }

                    Willy.





                    Comment

                    • Vertilka

                      #11
                      Re: marshal binary data file, written with C++, with my C# code

                      Willy,

                      I don't know if you notice but the binary data file was written by C++.
                      I am not sure that type bits written into the binary file, using C++,
                      is the same as type bits writen using .NET.

                      Vertilka

                      Comment

                      • Willy Denoyette [MVP]

                        #12
                        Re: marshal binary data file, written with C++, with my C# code


                        "Vertilka" <vertilka@gmail .com> wrote in message
                        news:1137695998 .043620.311950@ g47g2000cwa.goo glegroups.com.. .
                        | Willy,
                        |
                        | I don't know if you notice but the binary data file was written by C++.
                        | I am not sure that type bits written into the binary file, using C++,
                        | is the same as type bits writen using .NET.
                        |
                        | Vertilka
                        |

                        This is the first thing you should try to find out, right? You can't read a
                        file if you don't know the data types used in the file.
                        You said it's a binary data file, where is the data file written? On what
                        system (Windows, Unix, mainframe). Things to look for are endianess, char
                        encoding and eventual padding. If the file is written on Windows system,
                        then you are almost certain that the binary and floating point types are
                        exactly the same, more problematic are the char arrays and strings (which
                        are basically the same as arrays of chars once serialized), here you have to
                        know the encoding used so that you know how to read and to decode them.

                        Willy.




                        Comment

                        • Jon Skeet [C# MVP]

                          #13
                          Re: marshal binary data file, written with C++, with my C# code

                          Vertilka <vertilka@gmail .com> wrote:[color=blue]
                          > Jon, Nicholas,
                          > Thanks for your answers.
                          >
                          > Can you both post code snippets.
                          > Lets say that i have 8 bytes that i want to get a bouble from them.[/color]

                          double d = BitConverter.In t64BitsToDouble (Marshall.ReadI nt64(...));

                          Of course, that assumes it's in the right format. Worth trying to see.

                          --
                          Jon Skeet - <skeet@pobox.co m>
                          http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
                          If replying to the group, please do not mail me too

                          Comment

                          • Vertilka

                            #14
                            Re: marshal binary data file, written with C++, with my C# code

                            again, friends...

                            i have a byte array with data.
                            i know for example that the first 8 bytes are double.

                            now.
                            with this line:
                            double d = BitConverter.In t64BitsToDouble (Marshall.ReadI nt64(...));
                            i need to give intptr to ReadInt64.
                            how to convert byte array to intptr

                            thanks.

                            Comment

                            • Jon Skeet [C# MVP]

                              #15
                              Re: marshal binary data file, written with C++, with my C# code

                              Vertilka <vertilka@gmail .com> wrote:[color=blue]
                              > again, friends...
                              >
                              > i have a byte array with data.
                              > i know for example that the first 8 bytes are double.[/color]

                              In that case I'm not sure where the Marshal class comes in at all.
                              That's what's been confusing us, I suspect.
                              [color=blue]
                              > now.
                              > with this line:
                              > double d = BitConverter.In t64BitsToDouble (Marshall.ReadI nt64(...));
                              > i need to give intptr to ReadInt64.
                              > how to convert byte array to intptr[/color]

                              Use BitConverter.To Double then.

                              --
                              Jon Skeet - <skeet@pobox.co m>
                              http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
                              If replying to the group, please do not mail me too

                              Comment

                              Working...