zeh
- af0815
- Lazarusforum e. V.
- Beiträge: 6877
- Registriert: So 7. Jan 2007, 10:20
- OS, Lazarus, FPC: FPC fixes Lazarus fixes per fpcupdeluxe (win,linux,raspi)
- CPU-Target: 32Bit (64Bit)
- Wohnort: Burgenland
- Kontaktdaten:
Re: zeh
** wird oft bei einem array of Zeigern verwendet. Beispiel ist ein Array auf Strings (Strings = Array of Char).theo hat geschrieben:Hat jemand nen Plan von C?
Wie wäre folgender Prozedur Parameter umzusetzen?
uint8_t **dstptr
Ist das ein var PByte resp. Pchar ?
Vielleicht etwas für dich Pointer Tutorial oder hier Beispiel für Stringfeld
Blöd kann man ruhig sein, nur zu Helfen muss man sich wissen (oder nachsehen in LazInfos/LazSnippets).
Re: zeh
Danke. Ich hab jetzt den "eingebauten" Typen PPChar verwendet. Das trifft's wohl am besten.af0815 hat geschrieben: ** wird oft bei einem array of Zeigern verwendet. Beispiel ist ein Array auf Strings (Strings = Array of Char).
Trotzdem wird mir aus meinem konkreten Zusammenhang der Sinn davon nicht ganz klar.
Die Variable soll nämlich afaics kein "Array" von PChar halten sondern nur einen.
Re: zeh
ssize_t utf8proc_map( const uint8_t *str, ssize_t strlen, uint8_t **dstptr, int options)theo hat geschrieben:Danke. Ich hab jetzt den "eingebauten" Typen PPChar verwendet. Das trifft's wohl am besten.af0815 hat geschrieben: ** wird oft bei einem array of Zeigern verwendet. Beispiel ist ein Array auf Strings (Strings = Array of Char).
Trotzdem wird mir aus meinem konkreten Zusammenhang der Sinn davon nicht ganz klar.
Die Variable soll nämlich afaics kein "Array" von PChar halten sondern nur einen.
IMHO wird mit **dstptr die Adresse eines Zeigers übergeben. Das könnte auch darauf hindeuten, daß die Funktion utf8proc_map Speicher reserviert und über diesen Zeiger an den Aufrufer zurückliefert. Also z. B. so etwas wäre möglich:
Code: Alles auswählen
#include <stdio.h>
#include <inttypes.h>
#include <stdlib.h>
uint8_t *x;
void AllokiereX(uint8_t **dstptr)
{
*dstptr= malloc(100);
(*dstptr)[0]= 65;
(*dstptr)[1]= 66;
(*dstptr)[2]= 67;
(*dstptr)[3]= 0;
}
int main(void)
{
AllokiereX(&x);
printf("%s\n", x); // gibt ABC aus.
}
Gruß, Bernd.
Re: zeh
Tja, wenn das nur so einfach wäre..._Bernd hat geschrieben: Aber wenn Du den Source hast, dann kannst Du doch selber nachschauen, was die Funktion macht.
Also: Ich habe die Lib in zwei Varianten. Erstens als eingebundenes obj und zweitens als Versuch, das Ganze nach Pascal zu übersetzen.
Die Variante mit dem obj funktioniert.
Das ist so in Pascal geinterfaced:
function utf8proc_NFKC(str:Pchar):Pchar; cdecl; external;
Ich schicke einen PChar rein und bekomme einen PChar (String) zurück. Das Funktioniert.
Die C Seite dabei sieht so aus (hier nur die ersten Funktionen)
Code: Alles auswählen
uint8_t *utf8proc_NFKC(const uint8_t *str) {
uint8_t *retval;
utf8proc_map(str, 0, &retval, UTF8PROC_NULLTERM | UTF8PROC_STABLE | UTF8PROC_COMPOSE | UTF8PROC_COMPAT);
return retval;
}
ssize_t utf8proc_map(
const uint8_t *str, ssize_t strlen, uint8_t **dstptr, int options
) {
int32_t *buffer;
ssize_t result;
*dstptr = NULL;
result = utf8proc_decompose(str, strlen, NULL, 0, options);
if (result < 0) return result;
buffer = malloc(result * sizeof(int32_t) + 1);
if (!buffer) return UTF8PROC_ERROR_NOMEM;
result = utf8proc_decompose(str, strlen, buffer, result, options);
if (result < 0) {
free(buffer);
return result;
}
result = utf8proc_reencode(buffer, result, options);
if (result < 0) {
free(buffer);
return result;
}
{
int32_t *newptr;
newptr = realloc(buffer, result+1);
if (newptr) buffer = newptr;
}
*dstptr = (uint8_t *)buffer;
return result;
}
Nach Pascal übersetzt habe ich das so:
Code: Alles auswählen
function utf8proc_NFKC(str: puint8_t): Pchar;//puint8_t;
var
retval: Pchar;//puint8_t;
begin
utf8proc_map(str, 0, @retval, UTF8PROC_NULLTERM or UTF8PROC_STABLE or UTF8PROC_COMPOSE or UTF8PROC_COMPAT);
result := retval;
end;
function utf8proc_map(str: puint8_t; strlen: ssize_t; dstptr: ppuint8_t; options: integer): ssize_t;
var
buffer: pint32_t;
aresult: ssize_t;
newptr: pint32_t;
begin
dstptr^ := nil;
aresult := utf8proc_decomposer(str, strlen, nil, 0, options);
if aresult < 0 then
begin
result := aresult;
exit;
end;
buffer := GetMem(aresult * sizeof(int32_t) + 1);
if buffer = nil then
begin
result := UTF8PROC_ERROR_NOMEM;
exit;
end;
aresult := utf8proc_decomposer(str, strlen, buffer, aresult, options);
if aresult < 0 then
begin
freemem(buffer);
result := aresult;
exit;
end;
aresult := utf8proc_reencode(buffer, aresult, options);
if aresult < 0 then
begin
freemem(buffer);
result := aresult;
exit;
end;
begin
newptr := reallocmem(buffer, aresult + 1);
if newptr <> nil then buffer := newptr;
end;
dstptr^ := puint8_t(buffer);
result := aresult;
end;
int32_t = longint;
puint8_t = PByte;
pint32_t = plongint;
ppuint8_t=^puint8_t;
Kompilieren tut's, aber ich kriege nur den ersten Buchstaben zurück, nicht den ganzen String.
Siehst du den Denkfehler?
Re: zeh
Was ich z.B. nicht verstehe:
Was passiert hier:
*dstptr = (uint8_t *)buffer;
Wie kann man einen Plongint buffer auf PChar casten ??
Wenn ich mir bei der C Variante den buffer mit "Überwachte Ausdrücke" anschaue, also Pchar(buffer) dann steht da der ganze String drin, während bei Pascal nur das erste Zeichen steht, sofern es in ein Byte passt. (Umlaute sind falsch angezeigt).
Ich würde eigenlich auch das letztere erwarten. Was macht C da?
Was passiert hier:
*dstptr = (uint8_t *)buffer;
Wie kann man einen Plongint buffer auf PChar casten ??
Wenn ich mir bei der C Variante den buffer mit "Überwachte Ausdrücke" anschaue, also Pchar(buffer) dann steht da der ganze String drin, während bei Pascal nur das erste Zeichen steht, sofern es in ein Byte passt. (Umlaute sind falsch angezeigt).
Ich würde eigenlich auch das letztere erwarten. Was macht C da?
Re: zeh
Was C da macht, weiß ich auch nicht ganz genau. Mann könnte jetzt nachforschen. Ist mir aber zu aufwendig und raten möchte ich auch nicht 
Aber ich denke, Du hast da möglicherweise eine wunde Stelle gefunden. Vielleicht kannst Du mal auf die Schnelle den buffer und auch den newptr auf PByte setzen.
Gruß, Bernd.

Aber ich denke, Du hast da möglicherweise eine wunde Stelle gefunden. Vielleicht kannst Du mal auf die Schnelle den buffer und auch den newptr auf PByte setzen.
Gruß, Bernd.
Re: zeh
Der Longint wird aber gebraucht.
In diesem stehen die (maximal) vier Byte die einen UTF8Char ausmachen.
Ich kann die Daten schon abholen mit einem zweiten Puffer, auf den ich die Zeichen verteile z.B. (hier nur angetestet auf max 2 Byte).
So geht's schon, aber mir ist das ganze doch extremst Suspekt. Ich möchte wissen, wie C das macht.
Viellicht hat's im restlichen Code auch noch solche Schmankerl.
Danke für deinen Beistand.
In diesem stehen die (maximal) vier Byte die einen UTF8Char ausmachen.
Ich kann die Daten schon abholen mit einem zweiten Puffer, auf den ich die Zeichen verteile z.B. (hier nur angetestet auf max 2 Byte).
Code: Alles auswählen
var buf2:puint8_t;
...
buf2:=GetMem(aresult * 8 + 1);
count:=0;
for i:=0 to aresult do
begin
if Buffer[i]>$FF then
begin
buf2[count]:=Chr(Buffer[i]);
inc(count);
buf2[count]:=Chr(Buffer[i] shr 8);
end else
buf2[count]:=Chr(Buffer[i]);
inc(count);
end;
dstptr^ := puint8_t(buf2);
Viellicht hat's im restlichen Code auch noch solche Schmankerl.
Danke für deinen Beistand.

Re: zeh
Es lag in einer anderen Funktion. Zwei kleinere Fehler die ich nicht gesehen hatte.
Aber nichts, was ich jetzt als grosse Erkenntnis weitergeben könnte.
Es ist halt schnell mal was verbockt mit Pchar, Pointer-Offsets und Type-Casting etc.
Der Hauptfehler lag in diesen Zeilen (korrigiert):
uc := buffer[rpos];
wpos := wpos + utf8proc_encode_char(uc, PByte(buffer) + wpos);
Danke für die Unterstützung.
Aber nichts, was ich jetzt als grosse Erkenntnis weitergeben könnte.
Es ist halt schnell mal was verbockt mit Pchar, Pointer-Offsets und Type-Casting etc.
Der Hauptfehler lag in diesen Zeilen (korrigiert):
uc := buffer[rpos];
wpos := wpos + utf8proc_encode_char(uc, PByte(buffer) + wpos);
Danke für die Unterstützung.