Laden...

Übergabe von fixed sized array an Funktion

Erstellt von hsg vor 12 Jahren Letzter Beitrag vor 12 Jahren 719 Views
H
hsg Themenstarter:in
2 Beiträge seit 2011
vor 12 Jahren
Übergabe von fixed sized array an Funktion

Hallo zusammen,

seit ein paar Tagen beschäftige ich mich mit dem Thema C#.

Ich habe eine Struktur, die ich anschließend über das Netzwerk an einen Server (in Delphi geschrieben) sende. Damit das funktioniert habe ich in der Struktur fixed-Sized Arrays definiert, die ich dann füllen muss.

Das ganze sieht zur Zeit so aus:


   unsafe struct TLagerInfo {
        public int Befehl; 
        public fixed byte login[25];
        public fixed byte passwd[25];
        public fixed byte pool[40];
        public fixed byte RmNr[8]; 

    };

   unsafe {
            int nCount;
            byte[] cText;


            cText = new System.Text.ASCIIEncoding().GetBytes(clPools.Keys[Pool - 1]);
            nCount = Math.Min(cText.Length, 25);
            for (int i = 0; i < nCount; i++) rDaten.pool[i] = cText[i];
   }

Wie man an der Struktur sieht, sind es einige Felder, die ich so befüllen müsste. Also habe ich mir überlegt mir eine Funktion zu schreiben, die die Quelle und das entsprechende Feld in der Struktur übergeben bekommt und dann diese Kopieraktion durchführt.


        unsafe public void CopyField(string cSource, byte[] cDest)
        {
            int nCount;
            byte[] cText;

            cText = new System.Text.ASCIIEncoding().GetBytes(cSource);
            nCount = Math.Min(cText.Length, cDest.Length);
            for (int i = 0; i < nCount; i++) cDest[i] = cText[i];

        }

Bei Aufruf der Funktion in der folgenden Art CopyField(User, rDaten.pool);
mault mich der Compiler an. Fehlermeldung: > Fehlermeldung:

2-Argument: kann nicht von "byte*" in "byte[]" konvertiert werden.

Wie muss ich die Funktion richtig schreiben?

S
248 Beiträge seit 2008
vor 12 Jahren

Hallo hsg,

verwende diese Signatur:

unsafe public void CopyField(string cSource, byte* cDest, int length)

und übergib ebenfalls die Länge des (fixed size) Arrays.
Den Pointer wie ein normales .NET Array indizieren und auf die maximale Länge achten.

Grüße spooky

C
224 Beiträge seit 2009
vor 12 Jahren

hi hsg, ich würde die Verwendung von unsafe vermeiden.
Vielleicht hat ja jm. noch eine bessere Idee.
Nachfolgendes ist mir in Kürze eingefallen.
Es geht bestimmt noch besser (soviel Code für 3 Zeilen, wahnsinn ;-D):


        struct TLagerInfo2
        {
            //Datenfelder
            public int befehl;
            private string _login;
            public string login
            {
                get { return _login; }
                set { _login = GetFixedString(value, LOGIN_SIZE); }
            }
            private string _passwd;
            public string passwd
            {
                get { return _passwd; }
                set { _passwd = GetFixedString(value, PASSWD_SIZE); }
            }

            //Strukturgrößen
            public const int BEFEHL_SIZE = 4;
            public const int LOGIN_SIZE = 25;
            public const int PASSWD_SIZE = 25;

            public const int BEFEHL_POS = 0;
            public const int LOGIN_POS = BEFEHL_POS + BEFEHL_SIZE;
            public const int PASSWD_POS = LOGIN_POS + LOGIN_SIZE;

            public const int STRUCT_SIZE = BEFEHL_SIZE
                                         + LOGIN_SIZE
                                         + PASSWD_SIZE
            ;

            //Methoden

            private static string GetFixedString(string s, int maxlen)
            {
                if (string.IsNullOrEmpty(s)) return s;
                if (s.Length > maxlen)
                    throw new ArgumentException("String zu lang.")
                ;
                return s;
            }
            private static string GetStringFromBytes(byte[] b)
            {
                string s = System.Text.ASCIIEncoding.ASCII.GetString(b);
                int i = s.IndexOf('\0');
                if (i != -1) s = s.Substring(0, i);
                return s;
            }

            public byte[] ToBytes()
            {
                byte[] ret = new byte[STRUCT_SIZE];
                Array.Clear(ret, 0, ret.Length);
                
                byte[] b;

                b = BitConverter.GetBytes(befehl);
                b.CopyTo(ret, BEFEHL_POS);

                b = System.Text.ASCIIEncoding.ASCII.GetBytes(_login);
                b.CopyTo(ret, LOGIN_POS);

                b = System.Text.ASCIIEncoding.ASCII.GetBytes(_passwd);
                b.CopyTo(ret, PASSWD_POS);
                return ret;
            }

            public static TLagerInfo2 FromBytes(byte[] src, int srcIndex)
            {
                TLagerInfo2 ret = new TLagerInfo2();

                byte[] dst;
                dst = new byte[BEFEHL_SIZE];
                Array.Copy
                (
                    src, srcIndex + BEFEHL_POS, 
                    dst, 0, 
                    BEFEHL_SIZE
                );
                ret.befehl = BitConverter.ToInt32(src, srcIndex);

                dst = new byte[LOGIN_SIZE];
                Array.Copy
                (
                    src, srcIndex + LOGIN_POS, 
                    dst, 0, 
                    LOGIN_SIZE
                );
                ret._login = GetStringFromBytes(dst);

                dst = new byte[PASSWD_POS];
                Array.Copy
                (
                    src, srcIndex + PASSWD_POS, 
                    dst, 0, 
                    PASSWD_SIZE
                );
                ret._passwd = GetStringFromBytes(dst);
                
                return ret;
            }
        }

H
hsg Themenstarter:in
2 Beiträge seit 2011
vor 12 Jahren

Danke an CoLo und Spook. Die Lösung von CoLo gefällt mir wesentlich besser als mein Ansatz, daher werde ich das so umsetzen.