Autor Beitrag
OlafSt
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 486
Erhaltene Danke: 99

Win7, Win81, Win10
Tokyo, VS2017
BeitragVerfasst: Mi 21.08.13 14:22 
Hallo Freunde,

heute mal ein triviales Problem. Ich habe hier ein SDK, natürlich in C geschrieben. Nun müssen an verschiedene Routinen des SDK Zeichenketten übergeben werden. Natürlich sind diese allesamt als "char *" deklariert.

Greifen wir uns einfach eine solche Routine heraus:
ausblenden Quelltext
1:
2:
void UserLoggingMessageEvent(char *logmessage, int Loglevel, char* logChannel, uint64 logID, 
                             char* logTime, char* completeLogString);


In den neueren Delphi-Versionen sind nun alle Strings Unicode-Strings. Diese Strings dem SDK zu fressen zu geben geht erwartungsgemäß schwer in die Hose, ebenso sind die Rückgabewerte vom Typ char* ebenso Schrott. Immerhin haben wir damit schon mal herausgefunden, das das SDK kein Unicode unterstützt ;)

Nun wird es spannend. Ich übersetze obige Deklaration wie folgt:
ausblenden Delphi-Quelltext
1:
2:
procedure UserLoggingMessageEvent(const logmessage: PAnsiChar; logLevel: integer; const logChannel: PAnsiChar; 
                                  logID: uint64; const logTime: PAnsiChar; const completeLogString: PAnsiChar); cdecl;


Kein Problem. Aber sämtliche Zeichenketten müssen nun so übergeben werden:
ausblenden Delphi-Quelltext
1:
UserLoggingMessageEvent(PAnsiChar(myMessage[1]),1,PAnsiChar(myChannel[1]),1234,'','');					


Benutze ich nicht die Indizierung [1], wirft der Compiler massenhaft Warnungen aus: W1044 Bedenkliche Typumwandlung von string in PAnsiChar. Hat er ja auch recht, das wahre ist das Konstrukt nicht.

Ich habe nun überlegt, statt PAnsiChar einfach PAnsiString zu verwenden. Damit verschwinden die Warnungen. Aber nun sind plötzlich folgende Aufrufe unmöglich:
ausblenden Delphi-Quelltext
1:
UserLoggingMessageEvent('Debug Message',1,'Schwarzer Kanal',1234,'','');					

E2010 Inkompatible Typen 'PAnsiString' und 'string'. Typecasten nach PAnsiString hilft auch nix, ergibt einen E2089 Ungültige Typumwandlung. Auch doppeltes Typecasten PAnsiString(AnsiString('Schwarzer Kanal')) bringt das gleiche Resultat.

Gibt es eine Übersetzung nach Delphi XE4, ohne Myriaden an Typecasts zu machen oder die Warnung abschalten zu müssen ?

_________________
Lies, was da steht. Denk dann drüber nach. Dann erst fragen.
WasWeißDennIch
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 653
Erhaltene Danke: 160



BeitragVerfasst: Mi 21.08.13 17:43 
Und wenn Du myMessage, myChannel etc. als AnsiString deklarierst? Dann müsste es doch auch ohne die Indizierung funktionieren.
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19322
Erhaltene Danke: 1749

W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Mi 21.08.13 19:51 
Das sollte auch ohne Warnungen gehen:
ausblenden Delphi-Quelltext
1:
PAnsiChar(AnsiString(MeinString));					
Martok
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 3661
Erhaltene Danke: 604

Win 8.1, Win 10 x64
Pascal: Lazarus Snapshot, Delphi 7,2007; PHP, JS: WebStorm
BeitragVerfasst: Do 22.08.13 00:02 
PAnsiString ist schonmal ganz falsch, das ist nämlich ein Zeiger auf einen Delphi-String.

Diese Warnung W1044 gibt es analog auch bei FreePascal, dort lasse ich die tatsächlich meistens unterdrücken. Nutzwert ist 0, wenn man anfängt wild in der Gegend rumzucasten sollte man eh vorher drüber nachdenken. Da brauch ich keine Compilermeldung zu ;)

_________________
"The phoenix's price isn't inevitable. It's not part of some deep balance built into the universe. It's just the parts of the game where you haven't figured out yet how to cheat."
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19322
Erhaltene Danke: 1749

W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Do 22.08.13 07:14 
user profile iconMartok hat folgendes geschrieben Zum zitierten Posting springen:
Nutzwert ist 0, wenn man anfängt wild in der Gegend rumzucasten sollte man eh vorher drüber nachdenken.
Das ist nicht richtig, denn da viele Quelltexte aus der Zeit vor Delphi 2009 stammen, ist diese Meldung sehr wichtig, wenn man solchen Quelltext dann unter 2009+ kompiliert. Sonst müsste man die Casts manuell prüfen... denn es gibt leider viele Casts in nicht so guten Quelltexten auf PAnsiChar beim Aufruf von APIs obwohl nicht explizit die ...A Variante benutzt wurde...
OlafSt Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 486
Erhaltene Danke: 99

Win7, Win81, Win10
Tokyo, VS2017
BeitragVerfasst: Do 22.08.13 10:20 
user profile iconWasWeißDennIch hat folgendes geschrieben Zum zitierten Posting springen:
Und wenn Du myMessage, myChannel etc. als AnsiString deklarierst? Dann müsste es doch auch ohne die Indizierung funktionieren.


Die Idee ist nicht schlecht und habe ich auch gleich ausprobiert. Bei Routinen wie der genannten funktioniert das ganze auch prima. Aber leider nicht bei allen. Da gibt es dann auch noch solche bösen Dinger:

ausblenden Quelltext
1:
unsigned int getDefaultPlayBackMode(char **result);					


Hier gibt es einen Fehlercode als Ergebniswert (oder die übliche 0, wenn alles okay ist). Der DefaultPlaybackMode wird aber als Zeichenkette in result zurückgegeben. Diese Zeichenkette wird vom SDK alloziert und muß später mit einer eigenen SDK-Funktion wieder freigegeben werden. AnsiString ist hier also nicht möglich. Damit schließt sich auch ein var result: AnsiString aus.

In diesem SDK gibt es noch wesentlich beklopptere Konstrukte mit char ****result. Kein Witz - und spätestens hier ist klar, welches SDK ich hier gerade beackere ;)

Zitat:
PAnsiString ist schonmal ganz falsch, das ist nämlich ein Zeiger auf einen Delphi-String.


PAnsiString ist tatsächlich ein Zeiger auf einen Delphi-String, nämlich einen AnsiString. Und der läßt sich prima als nullterminierter String behandeln. Vermutlich war hier ein ShortString gemeint (die Dinger, die nur 255 Zeichen umfassen). Die sind hier wirklich unbrauchbar.

Weitere Ideen ?

_________________
Lies, was da steht. Denk dann drüber nach. Dann erst fragen.
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19322
Erhaltene Danke: 1749

W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Do 22.08.13 13:12 
user profile iconOlafSt hat folgendes geschrieben Zum zitierten Posting springen:
Die Idee ist nicht schlecht und habe ich auch gleich ausprobiert. Bei Routinen wie der genannten funktioniert das ganze auch prima. Aber leider nicht bei allen. Da gibt es dann auch noch solche bösen Dinger:

ausblenden Quelltext
1:
unsigned int getDefaultPlayBackMode(char **result);					
Da musst du einen echten PAnsiChar nehmen. Da du den Speicher dazu auch nicht allozieren musst, reicht das auch schon. Übergeben tust du das dann einfach als variablen Parameter.