Einen schönen guten Tag, ich hab noch ein "kleines" Problemchen,
bevor ich ins Wochenende starte und da könnt Ihr mir vermutlich helfen:
Ich möchte über meine Serielle Schnittstelle Strings übertragen,
Aber die Strings sind auch nicht mehr das, was sie bei Turbo Pascal mal waren...
Es gibt 16 verschiedene Varianten:
Doch nun zum Problem:
In meiner Komponente habe ich folgendes:
Code: Alles auswählen
Procedure WriteString(s:string);
var written:cardinal;
bein
WriteFile(fHandle,s,length(s),written,@Foverlapped);
end;
Die Windows API sieht ja so aus:
Code: Alles auswählen
BOOL WINAPI WriteFile(
_In_ HANDLE hFile,
_In_ LPCVOID lpBuffer,
_In_ DWORD nNumberOfBytesToWrite,
_Out_opt_ LPDWORD lpNumberOfBytesWritten,
_Inout_opt_ LPOVERLAPPED lpOverlapped
);
die FPC Datei "redef.inc" sieht das so aus:
Code: Alles auswählen
function WriteFile(hFile: THandle;
const Buffer;
nNumberOfBytesToWrite: DWORD;
var lpNumberOfBytesWritten: DWORD;
lpOverlapped: POverlapped
): BOOL; external 'kernel32' name 'WriteFile';
Wenn ich jetzt folgenden Code habe:
var s:string;
s:='Hallo';
WriteString(s);
Bei einem ShortString würden jetzt "vermutlich" 5 Bytes gesendet werden.
Das Längenbyte und die ersten 4 Buchstaben "Hall"
Das letzte "o" würde also fehlen,
Weil im ersten Byte befindet sich ja die Längenangabe und dann folgen die Asciizeichen.
demnach müste ich schreiben:
WriteFile(fHandle,s[1],length(s),written,@Foverlapped);
Aber was, wenn es kein ShortString ist ?
Bei einem Nullterminierten String muss ich s[0] verwenden.
Stellt sich mir grad die Frage woher die Funktion length eigentlich weis, wie die Länge des Strings ermittelt wird.
Also erscheint mir meine SendeRoutine für Strings relativ unkontrolliert
und daher meine Frage: wie mache ich das am Sinnvollsten.
In der Unit Synaser sieht das so aus:
Code: Alles auswählen
procedure TBlockSerial.SendString(data: AnsiString);
begin
SendBuffer(Pointer(Data), Length(Data));
end;
AnsiString ist 0 terminiert und hat einen RefCount und Length,
Laut http://wiki.freepascal.org/Character_an ... AnsiString
hat dann Refcount 4 Bytes und Length auch 4 Bytes, sofern ich das richtig interprtiert habe
was aber dem wiederspricht:
-- Ansistrings are strings that have no length limit --
Irgendwie verstehe ich die Stringverarbeitung nicht mehr.
Wird bei FPC Pointer(Data) automatisch der Zeiger 8 Bytes hinter den Speicher gesetzt
um Refcount und Length zu überbrücken und auf das erste Zeichen zu zeigen ?
Ich danke euch schonmal für jegliche Hinweise:
Siro
Nachtrag: ich könnte mit der Compiler Direktive {$H-} generell auf ShortString umstellen ?
Dann muss ich vermutlich meine Funktion wie folgt aufrufen:
WriteFile(fHandle,s[1],length(s),written,@Foverlapped);