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?
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
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;
}
}
Danke an CoLo und Spook. Die Lösung von CoLo gefällt mir wesentlich besser als mein Ansatz, daher werde ich das so umsetzen.