Erstellen von Unicode kompatiblen Userlibaries mit TailBite

Hier kannst du häufig gestellte Fragen/Antworten und Tutorials lesen und schreiben.
Benutzeravatar
ts-soft
Beiträge: 22292
Registriert: 08.09.2004 00:57
Computerausstattung: Mainboard: MSI 970A-G43
CPU: AMD FX-6300 Six-Core Processor
GraKa: GeForce GTX 750 Ti, 2 GB
Memory: 16 GB DDR3-1600 - Dual Channel
Wohnort: Berlin

Erstellen von Unicode kompatiblen Userlibaries mit TailBite

Beitrag von ts-soft »

Erstellen von Unicode kompatiblen Userlibaries mit TailBite (1.3 PR8)

Wie vielleicht von vielen bereits bemerkt, sind die meisten Userlibaries zur
Zeit nicht kompatible mit Unicode Anwendungen. Dies liegt daran, das die
Libraries als ASCII-compiliert werden. Wenn diese Libraries nun zu eine
Unicode Executable gelinkt werden, verstehen die Libraries nur noch
Bahnhof.

Echte Kompatiblität ist zur Zeit nicht möglich, aber die Möglichkeit, das
diese Libraries auch dann funktionieren, wenn sie zu einer
Unicode-Executable gelinkt wurden, besteht.

Hierzu sind 3 Maßnahmen erforderlich.

1.Stringparameter
Beispiel: (TailBite-Source)

Code: Alles auswählen

ProcedureDLL Foo(MyString.s)
	; bla
	ProcedureReturn bla
EndProcedure
Wenn wir diese Librarie in einer Unicode Anwendung aufrufen, erhält die
Funktion MyString als Unicode und versteht es nicht.

Abhilfe:
Wir erstellen eine weiter Procedure, mit dem anhängsel _UNICODE, diese
wird laut SDK-Doku, im Falle einer Unicode-Anwendung aufgerufen. Hier
wird der Unicode-String nach ASCII gewandelt!
Beispiel:

Code: Alles auswählen

ProcedureDLL Foo_UNICODE(MyString.s)
	; MyString per PeekS auslesen und einer temporären ACII Variablen zuordnen
	Protected MyString_Ansi.s = PeekS(@MyString, #PB_Any, #PB_Unicode)
	; wieder der Originalvariablen zuordnen (nicht unbedingt erforderlich)
	MyString = MyString_Ansi

	; Original Procedure mit ASCII-String aufrufen
	ProcedureReturn Foo(MyString)
EndProcedure
2.Stringrückgaben
Beispiel:

Code: Alles auswählen

ProcedureDLL.s Foo()
 ; bla
	ProcedureReturn "Bla"
EndProcedure
Abhilfe:
Auch hier nutzen wir obiges Feature mit _UNICODE
Beispiel:

Code: Alles auswählen

ProcedureDLL.s Foo_UNICODE()
  Protected Result.s = Foo(); Ascii ergebnis von Original Funktion holen
  Protected Result_Uni.s = Space(Len(Result) * 2); Speicher für UnicodeString

  PokeS(@Result_Uni, Result, #PB_Any, #PB_Unicode) ; Ergebnis von Foo() als Unicode in Buffer poken
  ProcedureReturn Result_Uni ; Unicode String zurückgeben
EndProcedure
3. API-Aufrufe
Alle API-Aufrufe in unser UserLib erfordern die ASCII Version,
UNICODE-Anwendungen nutzen jedoch autom. die UNICODE-Pedants.

Abhilfe:
Wir importieren alle API-Funktionen in unserem Librariesource, als
ASCII-Variante

Code: Alles auswählen

Import "user32.lib"
  MessageBoxA(Window.l, Body.s, Title.s, Flags.l)
EndImport
Jetzt dürfen wir im Librarie-Source aber nur noch MessageBoxA
verwenden!

Ich hoffe mal, diese Infos sind für den einen oder anderen Hilfreich beim
erstellen von UserLibs

Für eine Übersetzung, die im engl. Forum gepostet werden kann, wäre ich
dankbar.

Gruß
Thomas, der hoffentlich nicht zuviele Fehler eingebaut hat
PureBasic 5.73 LTS | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Nutella hat nur sehr wenig Vitamine. Deswegen muss man davon relativ viel essen.
Bild
Benutzeravatar
remi_meier
Beiträge: 1078
Registriert: 29.08.2004 20:11
Wohnort: Schweiz

Beitrag von remi_meier »

Habs jetzt nicht getestet, aber ich denke, das du das schon gemacht hast :D
Also wenn die PB-internen Dinge so stimmen, kann man das wohl als
Übergangslösung verwenden. Trotzdem, wie du sicher selber weisst, ist
der Aufwand zu gross, und da dieser 'Hack' sowieso meist sein Ziel ver-
fehlt, würde ich mir die Mühe sparen. Gerade die Unterstützung von
anderen Sprachen ist so natürlich nicht möglich, was ja Sinn und Zweck
von Unicode ist...
Kurzes Beispiel:

Code: Alles auswählen

; Als Unicode kompilieren.
ProcedureDLL.l NPeekS(*mem.CHARACTER, lLength.l = -1, lFlag.l = 0)
  Protected s.s, *t, lMemLen.l
  
  If lFlag
    Select lFlag
      Case #PB_Unicode
          lMemLen = WideCharToMultiByte_(#CP_ACP, 0, *mem, lLength, *s, 0, 0, 0)
          *s = AllocateMemory(lMemLen)
          WideCharToMultiByte_(#CP_ACP, 0, *mem, lLength, *s, lMemLen, 0, 0)
          
          ProcedureReturn *s
    EndSelect
    
  EndIf
EndProcedure


s.s = "日本語"

Debug s

Debug PeekS(NPeekS(@s, -1, #PB_Unicode), -1, #PB_Ascii)
Aber immerhin: Kompilieren lassen sich die Libs dann anscheinend und
für Programme, die nur Libs benutzen zur Ausgabe von englischen Texten,
kann man diesen Tipp sicher anwenden.
Benutzeravatar
ts-soft
Beiträge: 22292
Registriert: 08.09.2004 00:57
Computerausstattung: Mainboard: MSI 970A-G43
CPU: AMD FX-6300 Six-Core Processor
GraKa: GeForce GTX 750 Ti, 2 GB
Memory: 16 GB DDR3-1600 - Dual Channel
Wohnort: Berlin

Beitrag von ts-soft »

Ist auch nur dafür gedacht :wink:
Das dadurch keine Unicode-Unterstützung zustande kommt, ist mir klar, aber
die Libs funktionieren wenigstens, insofern sie keine Zeichen aus dem
erweiterten Zeichensatz benötigen.
PureBasic 5.73 LTS | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Nutella hat nur sehr wenig Vitamine. Deswegen muss man davon relativ viel essen.
Bild
Antworten