Wie ts-soft sagte: Mach eines von beidem zuerst (4.20->4.50 oder Unicode) und erst wenn du mit dem Ergebnis zufrieden bist das andere. Sonst hast du nacher irgendwo einen Fehler im Program und weißt nicht ob es jetzt an dem Versionssprung liegt oder an den Unicode-Änderungen.
Für die Umstellung 4.20 -> 4.50
Zunächstmal gab es dazwischen einige inkompatible Änderungen, die dir beim Compilieren mit 4.50 direkt als Syntax-Fehler oder als Warnung ins Gesicht springen werden. Das ist etwas Arbeit diese Dinge zu ändern, aber es ist wenigstens keine Gefahr für irgend welche versteckten Bugs die man später suchen muss.
Die meisten solchen Änderungen waren in 4.30 (siehe Geschichte in der Hilfe):
- Geändert: CountList() in ListSize()
- Geändert: ClearGadgetItemList() in ClearGadgetItems()
- Geändert: CameraProjection() in CameraProjectionMode()
- Geändert: AddElement() und entsprechende Befehle geben jetzt einen Zeiger auf den Start der Daten zurück
- Geändert: ComboBoxGadget() Höhe ist jetzt die tatsächliche Gadget-Höhe
- Geändert: #Long, #Byte, #Word etc. in #PB_Long, #PB_Byte, #PB_Word etc. zwecks Konsistenz
- Geändert: RotateEntity(), RotateCamera() und RotateBillboard() x,y Rotations-Achsen
- Geändert: CameraFOV() Winkel von Bogenmaß in Grad
- Geändert: Array und LinkedList parameter in Prozeduren benötigen nun das 'Array' oder 'List' Schlüsselwort
- Entfernt: StrQ(), HexQ(), BinQ(), ValQ()
- Entfernt: ChangeListIconGadgetDisplay(), ersetzt durch ein Gadget-Attribut
- Entfernt: ButtonImageGadget() Rückwärts-Kompatibilität
- Entfernt: CreateGadgetList(), erfolgt jetzt bei OpenWindow() automatisch
- Entfernt: CopyTexture(), TextureOutput()
Ein paar auch in 4.40:
- Geändert: Call(C)Function(Fast) Parameter wurden geändert von 'Any' in 'Integer'.
- Geändert: OpenScreen() akzeptiert jetzt FlipModus und RefreshRate
- Geändert: FlipBuffers() unterstützt keinen optionalen Parameter mehr
- Entfernt: #PB_Image_DisplayFormat ist jetzt "veraltet" (der Wert wurde auf 24 gesetzt, um standardmäßig 24Bit zu haben)
- Entfernt: SetRefreshRate() wurde entfernt, der Parameter befindet sind jetzt in OpenScreen()
Hier also einfach das Program mit 4.50 Compiliern und diese Dinge Ändern bis der Compiler nicht mehr meckert. (Das ist der einfache Teil)
In 4.30 gab es auch eine Änderung bezüglich dem 'Read' Schlüsselwort die vom Compiler nicht als Fehler angezeigt wird, aber eventuell geändert werden muss. Siehe den ersten Teil folgendes Blog-Posts für Details:
http://www.purebasic.fr/blog/?p=42
Falls du 64bit wirklich in Angriff nehmen willst ist der Rest davon auch sehr informativ.
Falls dein Programm 2DDrawing-Befehle von PB mit API Vermischt, solltest du auch folgenden Post lesen:
http://www.purebasic.fr/blog/?p=196
Das wars von den nötigen Änderungen für den Versionssprung. Der 4.50-Schritt hat keine großen Inkompatibilitäten mit sich gebracht. Je nach Programmgröße ist das schon etwas an Arbeit (vorallem wegen den Änderungen in 4.30), aber ich denke es lohnt sich schon.
Für den Umstieg auf Unicode:
Volker Schmid hat geschrieben:Was gibt es allgemein zu beachten? Ich habe viele String-Funktionen (base64 de/encode, lesen und speichern als Dateien, ini-Dateien etc.). Gibt es besondere Fallstricke? Vor allem wegen Unicode?
INI-Dateien:
Wenn du die Preferences-Lib verwendest gibt es keine Probleme. Im Unicode-Modus wird hier in UTF-8 gespeichert, aber sowol Ascii als auch UTF-8 können von Ascii und Unicode PB-Programmen gelesen werden. Das heißt ein Datenaustausch ist generell problemlos. Was PMV hier zu den Preferences geschrieben hat ist komplett falsch. Nur wenn ein Unicode-Program einen String mit nicht-Ascii Zeichen in die Preferences schreibt und ein Ascii-Programm das liest bekommt es nur Leerzeichen.
Lesen und Speichern von Dateien:
Hier wird im Unicode-Modus auch standardmäßig UTF-8 verwendet. Damit sind Dateien von einem Ascii-Program soweit lesbar wenn sie keine Sonderzeichen enthalten haben. Falls du hier weiterhin nur als Ascii speichern willst (oder von jetzt an nur als Unicode) dann musst du das als Flag in ReadString/WriteString angeben.
Base64 de/encode:
Hier wirst du Änderungen machen müssen. Die Base64-Funktionen sind in dem Sinne keine String-Funktionen. Sie arbeiten auf Speicherbereichen und ändern desshalb im Unicode-Modus ihr verhalten nicht. Wenn du also die Base64-Funktionen direkt auf PB-Strings verwendest hast du ein Problem, weil sie weiterhin nur Ascii-Zeichen produzieren (was nebenbei ja auch der Sinn von Base64 ist). Leider macht das das Beispiel in der Hilfe auch so. Am besten verwendest du hier nur Speicher mit AllocateMemory() und liest/schreibst das Ergebnis dann mit PokeS/PeekS mit dem #PB_Ascii flag wenn du es in einem String haben willst. Dann wird das auch in Unicode funktionieren.
Das gleiche gilt übrigens auch für hashes wie MD5:
MD5FingerPrint() wird gerne verwendet, um ein Passwort zu hashen, oft in dieser Art:
Im Unicode-Modus wird hier ein anderer Hash herraus kommen, weil der Password$-String im Speicher jetzt eben zwei Bytes pro Zeichen hat. Wenn man hier das gleiche Ergebnis haben will wie im Ascii-Modus dann muss man den String eben zuerst in Ascii umwandeln.
Volker Schmid hat geschrieben:Ich nutze auch viel UTF-8. Dort sind Funktionen wie
verwendet. Muss ich da viel umstellen?
Das wird so nicht mehr funktionieren. In einem Ascii-Programm klappt das weil UTF-8 Sequenzen sich auch als Ascii behandeln lassen (das ist ja der Sinn von UTF-8). In einem Unicode-Programm wird aber erwartet das "strResult.s" je zwei Bytes pro Zeichen verwendet. Wenn du jetzt da so einfach UTF-8 rein schreibst kommt da warscheinlich irgendwas Chinesisches dabei raus
Auch hier würde ich empfehlen als Ziel einen AllocateMemory()-Bereich zu verwenden und nicht einen anderen String.
Volker Schmid hat geschrieben:Wie schaut es mit Strings aus, welche heute als Pointer an DLL's übergeben werden und von DLL's so erhalten werden:
Code:
strMsg.s = Space(128) ; return buffer
lngRet.l = CallFunction(#CryptLibrary, "API_ErrorLookup", @strMsg, Len(strMsg.s), Erg.l)
Sind da Probleme zu erwarten (so von wegen Unicode)?
Wenn die DLL Ascii-Strings erwartet dann muss auch hier geändert werden. Für die Parameter die an die DLL Übergeben werden kann man die Arbeit der Umwandlung von PB machen lassen wenn man Prototypen verwendet. Hier ein Beispiel:
Code: Alles auswählen
; Die DLL-Funtion erwarten einen String im Ascii-Format als Parameter
Prototype MyFunctionType(Parameter.p-ascii) ; siehe "Pseudotypen" in der PB Hilfe
MyFunction.MyFunctionType = GetFunction(#Library, "MyFunction")
MyFunction("Dies wird automatisch in Ascii umgewandelt")
In deinem Beispiel geht es aber um die Rückgabe, hier gibt es keine Automatik. Auch hier ist die Lösung: Speicher mit AllocateMemory() anlegen, Funktion aufrufen, Ergebnis mit PeekS(..., #PB_Ascii) in einen PB String umwandeln, Speicher freigeben.
Volker Schmid hat geschrieben:Was ist mit den fast ausschliesslich Long Datentypen? Können die so bleiben oder sollte ich besser gegen Integer tauschen? Vor- und Nachteile? Sind DLL und allgemein API Pointer ohne Gefahr als Integer zu verwenden? Unter 32 Bits sind die ja zu Long identisch. Und was passiert, wenn ich dochmal auf 64 Bit gehen möchte?
Für einen 64bit-Umstieg wirst du hier Änderungen machen müssen, sonst nicht (siehe:
http://www.purebasic.fr/blog/?p=42). Auch hier gilt: Eins nach dem Anderen. Wenn du auf 4.50, Unicode und 64bit gleichzeitig umsteigen willst kriegst du ne Menge Magenschmerzen.
Volker Schmid hat geschrieben:Was machen Library's wie PureZIP, wenn die Anwendung als Unicode ausgeführt wird?
Da musst du den Autor fragen.
Volker Schmid hat geschrieben:
Macht es denn Sinn, so ein Projekt auf 4.50 zu migrieren?
Wenn es einen Grund dafür gibt, würde ich sagen ja. Wenn du zum Beispiel eines der neueren Features verwenden willst. Es ist Arbeit, aber es ist machbar. Wenn du aber mit den Möglichkeiten von 4.20 für dieses Projekt zufrieden bist und auch sonst keinen Grund hast zu migrieren würde ich mir die Arbeit sparen, frei nach dem Motto "never change a working system".
P.S.: Für jeden Leser dieses Posts wird ein Zuschlag wegen Überlänge fallig!