Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Win32/Win64 API (native code) (https://www.delphipraxis.net/17-win32-win64-api-native-code/)
-   -   Delphi Type _OSVERSIONINFOA - Verständnisproblem (https://www.delphipraxis.net/91679-type-_osversioninfoa-verstaendnisproblem.html)

Mazel 8. Mai 2007 16:21


Type _OSVERSIONINFOA - Verständnisproblem
 
Hallo,

Ich habe ein kleines Verständisproblem mit der Typ-Deklaration von verschiedenen Typen. Weil ich gerade TOSVersionInfo gebraucht habe, nehme ich dies als Beispiel:
In der Windows.pas ist _OSVERSIONINFOA folgendermaßen deklariert:
Delphi-Quellcode:
type
  POSVersionInfoA = ^TOSVersionInfoA;
  POSVersionInfoW = ^TOSVersionInfoW;
  POSVersionInfo = POSVersionInfoA;
  _OSVERSIONINFOA = record
    dwOSVersionInfoSize: DWORD;
    dwMajorVersion: DWORD;
    dwMinorVersion: DWORD;
    dwBuildNumber: DWORD;
    dwPlatformId: DWORD;
    szCSDVersion: array[0..127] of AnsiChar; { Maintenance string for PSS usage } 
  end;

  _OSVERSIONINFO = _OSVERSIONINFOA;
  TOSVersionInfoA = _OSVERSIONINFOA;
  TOSVersionInfoW = _OSVERSIONINFOW;
  TOSVersionInfo = TOSVersionInfoA;
  OSVERSIONINFOA = _OSVERSIONINFOA;
Nun, zunächst wollte ich wissen, was das 'A' und das 'W' bedeutet? Ich nehme an Ansi und Wide aber warum wird das getrennt behandelt?

Desweiteren verstehe ich nicht, warum der eigentliche Type _OSVersionInfoA so oft "hin und her" gesetzt wird. Also warum ist nicht
TOSVersionInfo = _OSVERSIONINFOA sondern erst
TOSVersionInfoA = _OSVERSIONINFOA und TOSVersionInfo = TOSVersionInfoA?

Ich hoffe mir kann jemand eine Antwort geben.

Gruß
Mazel

CCRDude 8. Mai 2007 17:27

Re: Type _OSVERSIONINFOA - Verständnisproblem
 
Das wird getrennt behandelt, weil die Windows-API das auch getrennt behandelt (sehr viele Funktionsaufrufe heißen auch FunktionsnameA und FunktionsnameW, wobei dann FunktionsnameA auch als Funktionsname verwendet wird).

Und das Namenshickhack mit mehreren Namen für denselben Typ hängt wahrscheinlich damit zusammen, daß die großgeschriebene Variante erst einmal die direkte Übersetzung aus einem C-Header ist (so kann man mal eben auch ein C-Beispiel direkt übersetzen, ohne erst den komfortableren Pascal-Namen zu kennen), und die Variante mit T und Groß-/Kleinschreibung danach noch einmal für bessere Lesbarkeit, der Pascal-Schreiber ist da schließlich verwöhnt ;)

Mazel 9. Mai 2007 12:35

Re: Type _OSVERSIONINFOA - Verständnisproblem
 
Das heißt also eigentlich für mich, dass ich ohne Problem gleich folgendes schreiben könnte:
Delphi-Quellcode:
type
  TOSVersionInfo = record
    dwOSVersionInfoSize: DWORD;
    dwMajorVersion: DWORD;
    dwMinorVersion: DWORD;
    dwBuildNumber: DWORD;
    dwPlatformId: DWORD;
    szCSDVersion: array[0..127] of AnsiChar; { Maintenance string for PSS usage } 
  end;

Muetze1 9. Mai 2007 14:08

Re: Type _OSVERSIONINFOA - Verständnisproblem
 
Ja, was dann aber explizit der Ansi Variante entspricht. Die Wide Variante hätte am Ende ein Array of WideChar und somit einen doppelt so grosses Member an der Stelle.

OldGrumpy 9. Mai 2007 14:32

Re: Type _OSVERSIONINFOA - Verständnisproblem
 
Bei solchen "dann kann ich ja einfach"-Aktionen bitte immer auch bedenken dass es Systeme gibt, auf denen die Variante ohne Suffix eben NICHT die Ansi- sondern die Wideversion ist. Wenn also Code geschrieben wird der auf mehr als dem eigenen Rechner zuhause laufen soll, dann lieber die vorhandenen Typen nehmen, man spart sich später dann viel Aufwand. Nebenbei sind die Wideversionen auf WinNT aufwärts per se (wenn auch marginal) schneller, weil der Kernel immer mit Widetypen arbeitet und für die Ansi-Aufrufe nochmals Wandlungen zwischen Ansi und Wide und wieder zurück notwendig werden.

Mazel 9. Mai 2007 15:32

Re: Type _OSVERSIONINFOA - Verständnisproblem
 
So ganz verstanden habe ich deine Aussage nicht, genauer, den ersten Teil. Das mit den Umwandlungen ist klar, aber nicht
Zitat:

Zitat von OldGrumpy
[..], dass es Systeme gibt, auf denen die Variante ohne Suffix eben NICHT die Ansi- sondern die Wideversion ist.


Bernhard Geyer 9. Mai 2007 15:36

Re: Type _OSVERSIONINFOA - Verständnisproblem
 
Zitat:

Zitat von Mazel
So ganz verstanden habe ich deine Aussage nicht, genauer, den ersten Teil. Das mit den Umwandlungen ist klar, aber nicht
Zitat:

Zitat von OldGrumpy
[..], dass es Systeme gibt, auf denen die Variante ohne Suffix eben NICHT die Ansi- sondern die Wideversion ist.


Wenn du mal mit einem Delphi-64-Bit-Compiler compilieren willst könnte es probleme geben. Dort gibt es AFAIK keine ANSI-Versionen der API mehr.

Mazel 9. Mai 2007 15:40

Re: Type _OSVERSIONINFOA - Verständnisproblem
 
Wenn ich jetzt aber als Beispiel die WindowsVersion ermitteln will verwende ich doch trotzdem TOSVersionInfo, der aber für Ansi angeführt ist, wie komme ich dann zu der Wide-Version?
Ich denke, hier im Forum nur den Type TOSVersionInfo für Ansi zu finden.

OldGrumpy 9. Mai 2007 15:55

Re: Type _OSVERSIONINFOA - Verständnisproblem
 
Kleines Beispiel: Wenn ich ein japanisches Windows nehme, dann sind da API-Aufrufe ohne Suffix generell die Wide-Varianten. Man erspart sich viel Arbeit für die Zukunft wenn man so früh wie möglich komplett auf Widetypen umsteigt - Die nötigen Wandlungen macht bei Delphi eh fast immer Compilermagic. Dafür laufen die Programme dann auch ohne viel Klimmzüge in exotischen Umgebungen :) Der Kernel arbeitet intern eh immer mit Widetypen und konvertiert für die Ansi-APIs transparent hin und her. Das kostet zwar nur marginal Zeit, aber... Ganz fiese Stolperfalle sind allerdings APIs die in Ansi und Wide unterschiedliche Parameter erwarten (ja, sowas gibts!), immer lieber nochmal in der MSDN nachschauen. Ich stell meinen alten Code Stück für Stück auf Wide um, immer wenn ich mal wieder ne Funktion oder Klasse recycle, wird die gleich entsprechend umgebaut. Win 9x-Kompatibilität ist bei meinen Projekten gottseidank gar kein Thema. Das ist gleichzeitig auch wohl fast der einzige Grund, überhaupt noch mit den Ansitypen zu arbeiten.

Mazel 9. Mai 2007 16:23

Re: Type _OSVERSIONINFOA - Verständnisproblem
 
Der Grund für die Frage ist eigentlich nur, dass ich ein kleine Funktion schreiben will, die ermittelt, ob das vorhandene System NT-Plattform ist oder nicht. Da GetVersionEx die einzigste Funktion aus der Windows.pas wär, wollte ich sie in meine Unit aufnehmen. Dazu auch den Typ. NUn dachte ich, ich könnte das so machen:
Delphi-Quellcode:
type
  TOSVersionInfo = record
    dwOSVersionInfoSize: DWORD;
    dwMajorVersion: DWORD;
    dwMinorVersion: DWORD;
    dwBuildNumber: DWORD;
    dwPlatformId: DWORD;
    szCSDVersion: array[0..127] of AnsiChar;
  end;
.
.
function GetVersionEx(var lpVersionInformation: TOSVersionInfo): LongBool; stdcall;
.
.
implementation

function GetVersionEx; external 'kernel32.dll' name 'GetVersionExA';
Würde das so also nicht auf anderen System möglicher Weise funktionieren? Stattdessen sollte ich
Delphi-Quellcode:
szCSDVersion: array[0..127] of WideChar;
.
.
function GetVersionEx; external 'kernel32.dll' name 'GetVersionExW';
verwenden?

Bernhard Geyer 9. Mai 2007 16:25

Re: Type _OSVERSIONINFOA - Verständnisproblem
 
Zitat:

Zitat von OldGrumpy
Kleines Beispiel: Wenn ich ein japanisches Windows nehme, dann sind da API-Aufrufe ohne Suffix generell die Wide-Varianten.

Falsch! Der Compiler bzw. die compilierte Exe "erkennt" nicht das es jetzt ein japanisches Windows ist auf dem es läuft. Die Bindung ist immer auf die Ansi-Version der API-Funktion/Struktur.

Dort gibt es auch Ansi und Wide-Versionen. Jedoch ist die Ansi-Codepage (wie auch auf chinesischen Windows) so das mehrere Ansi-Characters ein Zeichen darstellen! Damit funktioniert jeder Code nicht mehr korrekt der hart Strings abschneidet oder einzelne Characters aus Strings ändert. Ein String der z.B. 30 1-Byte-Characters beinhaltet ist letztendlich nur 10 (Wide-)Characters lang.

DGL-luke 9. Mai 2007 16:35

Re: Type _OSVERSIONINFOA - Verständnisproblem
 
Vielleicht meinte OldGrumpy ja, dass ein japanisches Kompilat die Wideversionen verwenden würde.

OldGrumpy 9. Mai 2007 16:41

Re: Type _OSVERSIONINFOA - Verständnisproblem
 
@DGL-luke: Ja, letzteres :) Je nach Compilerumgebung kann der "normale" API-Name entweder auf die A(nsi)- oder W(ide)-Variante gemappt sein. Bin heute irgendwie nicht ganz bei der Sache :(

Edit (2x): Eigen-DAU korrigiert ;)

Bernhard Geyer 9. Mai 2007 16:43

Re: Type _OSVERSIONINFOA - Verständnisproblem
 
Zitat:

Zitat von DGL-luke
Vielleicht meinte OldGrumpy ja, dass ein japanisches Kompilat die Wideversionen verwenden würde.

Dazu müßte ja der Quellcode der VCL schon soweit vorbereitet sein das String als Widestring umgesetzt wird und es nicht an Millionen Stellen kracht. Und das kann ich mir beim besten Willen für das Japanische Delphi nicht vorstellen.

Mazel 9. Mai 2007 17:11

Re: Type _OSVERSIONINFOA - Verständnisproblem
 
@OldGrumpy, hast du dich hiermit
Zitat:

Ja, letzteres :) Je nach Compilerumgebung kann der "normale" API-Name entweder auf die A(nsi)- oder W(ide)-Variante gemappt sein.
auf meine Frage bezogen?

OldGrumpy 9. Mai 2007 17:24

Re: Type _OSVERSIONINFOA - Verständnisproblem
 
Nein, meine Antwort da bezog sich auf DGL-luke, aber generell würde ich dazu tendieren, die W-Apis zu nehmen. Auf Kernelebene ist der Umstieg schon länger komplett vollzogen, insofern werden die Ansi-Apis praktisch nur noch der Kompatibilität wegen mitgeführt.

Edit: Eigen-DAU korrigiert (*sigh*)

DGL-luke 9. Mai 2007 17:26

Re: Type _OSVERSIONINFOA - Verständnisproblem
 
Ich dementiere heftigst: Ich bin nicht Luckie!

OldGrumpy 9. Mai 2007 17:50

Re: Type _OSVERSIONINFOA - Verständnisproblem
 
ARGH! *schäm* :wall: :wall: :wall:

Ich editiere da oben jetzt nochmal alles :) Mea culpa :(

Mazel 10. Mai 2007 08:41

Re: Type _OSVERSIONINFOA - Verständnisproblem
 
So ganz klar ist die Sache für mich aber immer noch nicht, da ich nicht so oft die API verwende bzw. ich mich noch nicht so intensiv beschäftigt habe. Wenn ich eine Funktion zum ermitteln der Windowsversion schreibe, würde die Deklaration des Typen so aussehen, wenn ich die windows.pas nutzte:
Delphi-Quellcode:
function GetWinVer : string;
var
  OSVersionInfo   : TOSVersionInfo;

begin
  ZeroMemory(@OSVersionInfo, SizeOf(TOSVersionInfo));
  OSVersionInfo.dwOSVersionInfoSize := SizeOf(TOSVersionInfo);
  if GetVersionEx(OSVersionInfo) then
   begin
   end;
end;
Das würde doch der Ansi-Variante entsprechen ebenso der Aufruf der Funktion GetVersionEx.
Wenn ich das ganze kompiliere, verarbeite ich doch nur die Ansi-Variante. Demnach müsste das entstande Programm Probleme mit sich bringen, da der Typ _OSVERSIONINFOA verarbeitet und die API Funktion GetVersionExA gebraucht wird aber bei einem Rechner mit nur noch Wide-Version nicht vorhanden ist? Wenn ich die Funktion und den Typ selber in die Unit aufnehme, kann ich die Wide-Version verwenden aber eben nicht wenn ich die Windows.pas einbinde.

OldGrumpy 10. Mai 2007 09:35

Re: Type _OSVERSIONINFOA - Verständnisproblem
 
Bisher ist es bei Windows immer so, dass noch ewig lange diverse Rattenschwänze mitgeschleppt werden, um Abwärtskompatibilität zu sichern. (In Delphi gibts z.B. auch immer noch WinExec(), ein Überbleibsel aus Zeiten von Windows 3.x) Wenn 2011 wirklich der Vista-Nachfolger in den Startlöchern steht, womöglich mit .NET 4.0 *g* dann würde ich mich langsam aber nicht mehr darauf verlassen. Wer rechtzeitig umsteigt, hat weniger Probleme - sehr schön sehen konnte man das an der Treibersituation für 64-Bit-Systeme. XP x64 und auch Vista x64 quälen einen immer noch recht derbe durch nicht verfügbare Treiber für allerlei Hardware. Bei den Treibern bleibt den Herstellern nämlich gar nichts anderes übrig, als sich an den neuen Features zu orientieren, die 64-Bit-Varianten brauchen bei Kerneltreibern auch native 64-Bit-Treiber. Und obwohl Vista schon ewig lange für Entwickler verfügbar war, scheinen etliche Hersteller doch wohl TOTAL überrascht worden zu sein, dass Vista jetzt auf einmal in den Läden steht. Hoppla!


Alle Zeitangaben in WEZ +1. Es ist jetzt 23:14 Uhr.

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