Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   Pointer in C# (https://www.delphipraxis.net/126241-pointer-c.html)

Neutral General 20. Dez 2008 20:24


Pointer in C#
 
Hi,

Im Moment siehts so aus, dass ich übers Netzwerk Daten geschickt bekomme. Die Socketklasse von C# (bzw dem .NET Framework) macht das ja alles über Byte-Arrays. Soweit ja in Ordnung. Allerdings will ich jetzt dieses Byte Array in ein struct kopieren, bzw das Array so interpretieren können.

Das ganze ist allerdings scheinbar nicht so einfach -.-
Ich habe keinen Move befehl o.ä. gefunden mit dem ich die Bytes einfach verschieben/kopieren kann und ein Pointer des structtyps auf dieses Array funktioniert auch nicht.

Also mein Quelltext (= Müll) sieht so aus:

Code:
public struct TPlayerState
{
   public UInt16 id;
   public int x;
   public int y;
   public UInt32 color;
}


// ...
  byte[] buff = new byte[14];
  // Daten in buff lesen
  TPlayerState* x = (TPlayerState*)(byte*)buff[0]; //<---- *
// ...
*)
Zitat:

Zeiger und Puffer mit fester Größe können nur in einem nicht sicheren Kontext verwendet werden.
Ich versteh das nicht. Abgesehn davon, dass ich bei C# Pointer noch nicht so ganz verstanden hab glaub ich.

Also
Code:
Typ* x;
=

Delphi-Quellcode:
var x: ^Typ;
Code:
x = *var;
=

Delphi-Quellcode:
x := @var;
Stimmt das soweit? Und wie dereferenziert man in C#? Und was soll wie gesagt oben diese Meldung? -.-

In Delphi ist das alles unkomplizierter.....

Insider2004 20. Dez 2008 20:27

Re: Pointer in C#
 
C# ist managed code. Da gibt es keine Pointer. Dafür gibt es native Sprachen, wie Delphi oder C.

jfheins 20. Dez 2008 20:29

Re: Pointer in C#
 
Zitat:

Zeiger und Puffer mit fester Größe können nur in einem nicht sicheren Kontext verwendet werden.
Das heißt, es ist eigentlich schlecht (das gepointere) und deshalb must du (wenn du wirklich willst) einen unsafe-Block drumherum legen ;)

Apollonius 20. Dez 2008 20:33

Re: Pointer in C#
 
Unsafe Code würde ich in .NET versuchen zu vermeiden. Es geht praktisch immer ohne. Die Frage ist hier, ob du Einfluss auf das sendende Programm hast. Wenn ja, kannst du einfach auf beiden Seiten einen Standard-Serialisierungsmechanismus verwenden (in Java gibt es so etwas, mich würde es wundern, wenn das in .NET fehlte). Andernfalls kannst du die Daten manuell aus dem Byte-Array herausziehen. Ich bin mir ziemlich sicher, dass es noch einen direkten Weg gibt (es gibt schließlich sogar Attribute für die Struct-Ausrichtung), aber er fällt mir gerade nicht ein.

Neutral General 20. Dez 2008 20:39

Re: Pointer in C#
 
Hi,

Also letztendlich ist es mir egal, wie ich die Bytes in das struct Ding bekomme -.-

Hab Einfluss auf das Sendende Programm. Es ist ein Client, den ich in Delphi schreibe.
Was ist ein Standard-Serialisierungsmechanismus?

Klar könnte ich das ganze manuell ausm Array rausziehn, aber das ist doch viel zu umständlich und wenn mein Server mal viel zu tun hat, dann ist das doch unnötige Arbeit...

Phoenix 20. Dez 2008 20:40

Re: Pointer in C#
 
Aua!

.NET ist eine managed Runtime. Da hat man nicht mit Pointern zu arbeiten. Punkt. Dadurch, dass der Speicher von der Runtime verwaltet wird, hast Du nahezu gar keine Kontrolle darüber, wie ein Struct im Speicher aussieht. Das kann sich sogar je nach dem von einem Start der Applikation zum nächsten ändern. Anzunehmen, dass ein Struct ein bestimmtes Layout im Speicher hätte, ist in .NET grundlegend falsch (Insbesondere, wenn Du in C# einfach nur 'int' nimmst. Int ist nämlich zur Zeit ein Int32, kann aber ggf. auf 64bit Systemen je nach Optimierung auch auf einen Int64 mappen). Ausnahme: Du forcierst das über Attribute, aber das unterbindet dann zwangsläufig die Optimierung und kann hintenraus ordentlich performance kosten.

Du kannst den Code möglicherweise als unsafe deklarieren, aber damit kommst Du dann spätestens bei der CAS (Code Access Security) Probleme.

Schau Dir mal den Namespace System.Runtime.Serialization bzw. System.Runtime.Serialization.Formatters an. Da hats nen BinaryFormatter. Ich denke, das wäre der bessere Ansatz um Dein Struct aus dem empfangenen Stream zu füllen.

Dax 20. Dez 2008 20:43

Re: Pointer in C#
 
Und falls du doch darauf bestehst:

Code:
[StructLayout(LayoutKind.Sequential)]
public struct TPlayerState
{
   public UInt16 id;
   public int x;
   public int y;
   public UInt32 color;
}

// unsafe void MeineMethode
// ...
   byte[] buff = new byte[14];
   fixed(byte* xb = &(buff[0])) {
    TPlayerState* x = (TPlayerState*)xb;
   }
// ...
Aber Phoenix hat schon Recht. Wenn du die korrekten Serialization-Interfaces implementierst, kannst du das wunderbar ohne rumgepointere machen. Dazu gibt's im MSDN unter den entsprechenden Topics auch viele Beispiele ;)

Neutral General 20. Dez 2008 20:44

Re: Pointer in C#
 
Mh...

Ohne Pointer ist doof. :stupid:

Mal so nebenbei... Oder sollte man einen Server, der auch auf Linux laufen soll vielleicht doch eher mit C++ schreiben?

Wenn ich mir das hier so durchlese zweifel ich langsam daran, dass C# die richtige Sprache ist...

Dax 20. Dez 2008 20:45

Re: Pointer in C#
 
Zitat:

Zitat von Neutral General
Mal so nebenbei... Oder sollte man einen Server, der auch auf Linux laufen soll vielleicht doch eher mit C++ schreiben?

Wenn ich mir das hier so durchlese zweifel ich langsam daran, dass C# die richtige Sprache ist...

Mono

Apollonius 20. Dez 2008 20:49

Re: Pointer in C#
 
Die Klassen aus System.Runtime.Serialization sind genau das, was ich mit einem Standard-Serialisierungsmechanismus meinte. Eine nicht-native Sprache benötigt schließlich auch irgendeinen Mechanismus, Objektinstanzen zu speichern, ohne dabei gleich unsafe zu werden. Bezüglich des direkten Wegs habe ich mich übrigens getäuscht. Das war eben jene Geschichte mit dem StructLayout-Attribut, und das verwendet man nur in Zusammenhang mit unsafe oder unmanaged Code.

Neutral General 20. Dez 2008 20:50

Re: Pointer in C#
 
Zitat:

Zitat von Dax
Zitat:

Zitat von Neutral General
Mal so nebenbei... Oder sollte man einen Server, der auch auf Linux laufen soll vielleicht doch eher mit C++ schreiben?

Wenn ich mir das hier so durchlese zweifel ich langsam daran, dass C# die richtige Sprache ist...

Mono

Was genau ist Mono? Mono ist doch "nur" eine IDE oder?

mkinzler 20. Dez 2008 20:51

Re: Pointer in C#
 
Zitat:

Was genau ist Mono? Mono ist doch "nur" eine IDE oder?
Nein eine alternative Implementierung der VM, Runtime und diversen Kompilern

jfheins 20. Dez 2008 20:56

Re: Pointer in C#
 
Köntest du den Playerstate nicht einfach als Text übertragen? also z.B. dezimal mit Leerzeichen getrennt:

1273 -73674 25062 -7246284

Das kan man dann einfach trennen und einzeln zuweisen - oder kommt es sehr auf Geschwindigkeit an?

Edit: Alternativ kannst du ja auch sowas machen:

id = arr[0] + arr[1] << 8;
x = arr[2] + arr[3] << 8 + ...

Ein kleines bisschen Schreibarbeit, aber schneller als Strings ;)

Neutral General 20. Dez 2008 21:35

Re: Pointer in C#
 
Zitat:

Zitat von jfheins
...

Also das mit den Strings geht auf keinen Fall. Es kann gut sein, dass der Server später viel zu tun haben wird. Da darf der Server seine Zeit nicht mit irgendwelchen Strings verschwenden.

Zurzeit bin ich mir C++ am anschauen. Ich kann mich nicht so richtig mit diesen Frameworks anfreunden :?

Werde dann wohl entscheiden ob ich C++ oder C# nehme. Was ist denn objektiv gesehen geeigneter?

Phoenix 20. Dez 2008 21:47

Re: Pointer in C#
 
Zitat:

Zitat von Neutral General
Werde dann wohl entscheiden ob ich C++ oder C# nehme. Was ist denn objektiv gesehen geeigneter?

Eigentlich ist eine managed Umgebung (Java / .NET) genau das Richtige für solche Server. Sie skalieren sehr gut, optimieren sehr gut und bieten durch die schiere Größe des Frameworks für so ziemlich jede Aufgabe bereits fertige Klassen. Zudem brauchst Du Dich beim Entwickeln nicht um den Speicher zu kümmern. Der wird ja verwaltet. Zudem hat das ganze zwei weitere große Vorteile: Memory Leaks sind ausgeschlossen. Ein kleiner Fehler im Memory-Management in C++ und Dein Server produziert Memory Leaks. Die sind schwer zu finden und beeinflussen die Stabilität des Servers (irgendwann hat der Rechner halt keinen Speicher mehr). Nächster Punkt: Buffer Overflows sind ausgeschlossen. Da der Speicher von der Runtime verwaltet wird, wird da nichts bei irgendwelchen Copy-Operationen wo hin geschrieben, wo es nichts zu suchen hat und ggf. später ausgeführt wird. Insbesondere wenn Du einen Server schreibst der öffentlich läuft sollte dieses Sicherheitsplus auf jeden Fall für eine managed Umgebung sprechen.

Wenn Du mit C# nicht so gut zurecht kommst schau Dir mal Prism an :zwinker:

Aber ich denke, in .NET bist Du für so einen Server sehr gut aufgehoben. Und wenn Du im Prinzip vorne 'nur' Sockets und hinten z.B. eine Datenbank hast, dann läuft das ganze auf Mono auch ohne weiteres. Du kannst ja z.B. auch mit C# auf Windows direkt gegen Mono anstelle des .NET Frameworks von Microsoft entwickeln und testen. Dann läufts auch unter Linux *g*

Neutral General 20. Dez 2008 21:56

Re: Pointer in C#
 
Hi,

Also ich komme mit C# soweit eigentlich bisher ganz gut zurecht aber ich muss die Sache mit den Pointern wohl erstmal verdauen, weil... Wie soll ich nur ohne meine lieben Pointer programmieren? :cry: :mrgreen:

Naja ich werd mich wohl nochn bisschen mit C# und dem .NET auseinandersetzen müssen...

Ich kann aber den Server auch erstmal "ganz normal" in C# (SharpDevelop) programmieren und dann später einfach mit Mono kompilieren oder muss ich dann alles umbauen?

mkinzler 20. Dez 2008 21:58

Re: Pointer in C#
 
Zitat:

Ich kann aber den Server auch erstmal "ganz normal" in C# (SharpDevelop) programmieren und dann später einfach mit Mono kompilieren oder muss ich dann alles umbauen?
Kommt darauf an, welche (GUI-)Bibliothek du benutzt. Es gibt auch eine Monoversion von SharpDevelop ( MonoDevelop)

jfheins 20. Dez 2008 22:07

Re: Pointer in C#
 
Zitat:

Zitat von Neutral General
Ich kann aber den Server auch erstmal "ganz normal" in C# (SharpDevelop) programmieren und dann später einfach mit Mono kompilieren oder muss ich dann alles umbauen?

Wen Mono das ist, was ich glaube das es das ist, dann brauchst du es nicht nochmal kompilieren (bzw. das wird ja für dich gemacht) sondern einfach nur die exe-datei kopieren und läuft ;)

Das Compilieren zur IL ist noch plattformunabhängig und das JIT-Compiling wird ja transparent auf der Zielmaschiene durchgeführt ...

alzaimar 20. Dez 2008 22:24

Re: Pointer in C#
 
Was spricht eigentlich dagegen, die Daten in einen Stream zu schmeissen und dann Stück für Stück auszulesen? Da benötigt man doch keinen unmanaged code, Pointer o.ä... :gruebel:

Phoenix 21. Dez 2008 10:56

Re: Pointer in C#
 
Zitat:

Zitat von alzaimar
Was spricht eigentlich dagegen, die Daten in einen Stream zu schmeissen und dann Stück für Stück auszulesen? Da benötigt man doch keinen unmanaged code, Pointer o.ä... :gruebel:

Prinzipiell nichts. Das ist nämlich genau das, was der BinaryFormatter macht. Den baut man einmal für die Objektstruktur und gut ist. Den Rest erledigt das Framework.

Neutral General 21. Dez 2008 17:10

Re: Pointer in C#
 
Hi,

Habs jetzt so probiert:

Code:
[Serializable]
public struct TPlayerState
{
   public UInt16 id;
   public int x;
   public int y;
   public UInt32 color;
}

public static void RecClientData(object client)
{
   Socket csock = client as Socket;
   BinaryFormatter binf = new BinaryFormatter();
         
   byte[] buff = new byte[14]; // Größere Pakete kommen zurzeit eh nicht an, von daher hab ichs mal so fest drin.

   int len;
   while ((len = csock.Receive(buff,SocketFlags.None)) > 0)
   {      
      Stream ms = new MemoryStream();
      ms.Write(buff,0,buff.Length);
      ms.Position = 0;
   
      switch (buff[0])
      {
         case 0: Console.WriteLine("...");
            break;
         case 1: TPlayerState ps = (TPlayerState)binf.Deserialize(ms); // <---- *)
            Console.WriteLine(ps.y);
            break;
         default:break;
      }
// ....
*) Ausnahme System.Runtime.Serialization.SerializationExceptio n wurde im ausgeführten Programm ausgelöst:
Das Streamende wurde erreicht, bevor die Verarbeitung abgeschlossen wurde.

Kann mir da jemand sagen was ich falsch mache? Versenden tu ich das ganze so:

Delphi-Quellcode:
type
  TPlayerState = packed record
    id: Word; // 1
    x,y: Integer;
    color: TColor;
  end;

var data: TPlayerState;
begin
  data.id := 1;
  data.x := 20;
  data.y := 40;
  data.color := clred;
  Client.Send(@data,SizeOf(TPlayerState));
end;
Gruß
Neutral General

Apollonius 21. Dez 2008 17:12

Re: Pointer in C#
 
Du musst natürlich auch zum Serialisieren den BinaryFormatter verwenden.

Neutral General 21. Dez 2008 17:16

Re: Pointer in C#
 
Zitat:

Zitat von Apollonius
Du musst natürlich auch zum Serialisieren den BinaryFormatter verwenden.

Ja wie soll ich das denn machen? :roll:

Ich versende doch die Daten von einem Delphi Win32 Programm aus.

Da hab ich keinen Binary-Formatter....

Apollonius 21. Dez 2008 18:09

Re: Pointer in C#
 
Dann musst du entweder den unmanaged Weg gehen oder den Stream manuell parsen. Letzteres ist doch wirklich kein Problem.

Phoenix 21. Dez 2008 21:03

Re: Pointer in C#
 
Schau Dir das hier mal an. Da ist ein Artikel für einen CustomFormatter verlinkt. Könnte das sein, was Du brauchst.


Alle Zeitangaben in WEZ +1. Es ist jetzt 05:53 Uhr.

Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz