Autor |
Beitrag |
michaelarban
      
Beiträge: 34
|
Verfasst: Mo 28.06.10 21:48
Hallo,
ich beziehe mich auf den Artikel von Michael Puff:
www.michael-puff.de/...ikel/StringDLL.shtml
In diesem Artikel wird beschrieben, dass man (im Hauptprogramm "program DLLProg;")die Größe des zu reservierenden Buffers (Buffer: PChar;) herausfindet, in dem man die
funktion "func1" 2mal aufruft:
Hier der relevnate codeausschnitt:
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39:
| library StringDLL;
uses SysUtils;
function func1(s: PChar; Buffer: PChar; lenBuffer: Integer): Integer; stdcall; var foo: String; begin foo := 'foo'+ s; if Assigned(Buffer) then StrLCopy(Buffer, PChar(foo), lenBuffer); result := length(foo); end;
len := func1('bar', nil, 0); Str(len, s); try GetMem(Buffer, len + 1); len := func1('bar', Buffer, len + 1); Str(len, s);
finally FreeMem(Buffer); end; |
Frage:
Dieser einfacher Fall ist verständlich;
Aber wie ist es, wenn in func1 bspw. ein Verzeichnis gelöscht und der gelöschte Verzeichnisname als PChar zurückgegben werden soll? Ich kann die Funktion nicht mehr 2 mal aufrufen, da bereits beim 1. Aufruf das Verzeichnis gehöscht worden ist und ein 2.Aufruf keinen Sinn machen würde.
Wie kann finde ich in diesem Falle die Größe des zu reservierenden Buffers (im Hauptprogramm)?
PS: Sharemem soll nicht verwendet werden, nur PChar
danke
|
|
jaenicke
      
Beiträge: 19314
Erhaltene Danke: 1747
W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Di 29.06.10 07:02
Du kannst zum Beispiel auch gleich die maximale Anzahl Zeichens eines Pfads (müsste MAX_PATH sein) anfordern. Dann ist der Puffer auf jeden Fall groß genug und du bekommst einfach die tatsächliche Anzahl Zeichen zurück.
In dem von dir genannten zweistufigen Verfahren darf im ersten Aufruf noch nichts passieren. Sondern erst, wenn ein gültiger und ausreichend großer Puffer übergeben wurde.
Wenn du die Rückgabe des Wertes nur optional machen willst, kannst du das so machen: Quelltext 1: 2: 3: 4: 5:
| Buffer BufSize Aktion Rückgabe nil 0 ja keine <> nil 0 nein Buffergröße // ist im nächsten Fall auch drin, aber zur Verdeutlichung <> nil zu klein nein Buffergröße <> nil reicht ja entsprechender Wert | Das heißt du schaust ob der Buffer nil ist. Wenn ja, dann ist keine Rückgabe im Buffer gewünscht und du führst einfach die Aktion durch.
Wenn Buffer <> nil ist, dann schaust du dir die Buffergröße an. Ist diese zu klein, dann gibst du die benötigte Größe zurück und machst nichts. Wenn die Buffergröße ausreicht, dann führst du die Aktion durch und lieferst den Wert im Buffer.
Nebenbei:
Wenn du es genau so machst wie von dir oben beschrieben, dann fehlt dir im Grunde die Möglichkeit einen Fehlercode zurückzuliefern. Deshalb ist es evtl. sinnvoller die Buffergröße by reference zu übergeben und ggf. zu verändern. Dann kannst du in Result das Ergebnis der Funktion zurückliefern.
Dafür kannst du dann nicht einfach 0 übergeben, sondern musst eine Variable angeben.
|
|
michaelarban 
      
Beiträge: 34
|
Verfasst: Di 29.06.10 20:25
hallo jaenicke,
erstmal danke für deine Antwort.
Eine generelle Frage; könnte man auch folgenderweise vorgehen, um Strings zwischen Anwendung und DLL auszutauschen ohne Speicher zu allokieren?:
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33:
| procedure func1 (pcharInput : PChar; Out pcharOutput : PChar) var myString : String; begin myString := gibVieleX(); myString := myString + pcharInput ; pcharOutput := PChar (myString); end;
procedure testen() var pcharRein : Pchar; pcharRaus : PChar; ergebnis : String; begin rein := PChar ("gib mir Xe: "); func1(pcharRein, pCharRaus); ergebnis := String (pCharRaus); end; |
Frage:
- würde das denn nicht funktionieren (ohne irgendwelchen Speicher zu allokieren)??
Danke
|
|
Narses
      

Beiträge: 10183
Erhaltene Danke: 1256
W10ent
TP3 .. D7pro .. D10.2CE
|
Verfasst: Di 29.06.10 20:34
_________________ There are 10 types of people - those who understand binary and those who don´t.
|
|
michaelarban 
      
Beiträge: 34
|
Verfasst: Di 29.06.10 20:51
hallo,
ich verstehe nicht, wie ich ddann bei dem oben genannten Beispiel mit GetMem Speicherplatz für die Pchar-Variable (pcharRaus) in der Hauptanwendung reservieren soll, wenn ich nicht weiss wie groß in der DLL die Variable myString ist, denn bei jedem Aufruf hat dieseVariabe eine andere Anzahl von Xen.
Weisst du wie ich die richtige Speichergröße allokieren kann?
|
|
Narses
      

Beiträge: 10183
Erhaltene Danke: 1256
W10ent
TP3 .. D7pro .. D10.2CE
|
Verfasst: Di 29.06.10 21:22
Moin!
michaelarban hat folgendes geschrieben : | ich verstehe nicht, wie ich ddann bei dem oben genannten Beispiel mit GetMem Speicherplatz für die Pchar-Variable (pcharRaus) in der Hauptanwendung reservieren soll, wenn ich nicht weiss wie groß in der DLL die Variable myString ist, denn bei jedem Aufruf hat dieseVariabe eine andere Anzahl von Xen. |
Wenn du keine Obergrenze für die Buffergröße angeben kannst, dann bleibt nur, die Funktion mit einem Fehler abzubrechen, wenn der Buffer zu klein ist, da gibt´s leider keine andere Möglichkeit.
Das mit den Xen ist doch etwas schwammig, worum geht´s denn da wirklich, vielleicht gibt´s ja Alternativen.
cu
Narses
_________________ There are 10 types of people - those who understand binary and those who don´t.
|
|
michaelarban 
      
Beiträge: 34
|
Verfasst: Di 29.06.10 21:56
verstehe ich das richtig, dass der Buffer eine Obergrenze haben muss?
Wenn ich also weiss, dass die Funktion func1 nicht mehr als 1020 Xen zurückliefern wird, kann ich die Buffergröße bspw. auf 3000 setzen:
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33:
| procedure func1 (pcharInput : PChar; pcharBuffer : PChar) var myString : String; begin myString := gibVieleX(); myString := myString + pcharInput ; if Assigned(pcharBuffer) then StrLCopy(pcharBuffer, PChar(myString), Length(myString)); end;
procedure testen() var pcharRein : Pchar; pcharBuffer : PChar; ergebnis : String; begin pcharrein := PChar ("gib mir Xe: "); GetMem(pcharBuffer, 3000 + 1); func1(pcharRein, pcharBuffer); ergebnis := String (pcharBuffer); end; |
Frage:
wie sieht dann die String-Variable ergebnis aus, wenn bspw. nur 4 Xen zurückgeliefert wreden:
"gib mir die Xe: XXXX"
oder so
"gib mir die Xe: XXXXvynbcviuhqp98tflkjh3453409lkgdfgsdfglg pwe96230909tu ....datenmüll bis zur 3000.stelle#0" , 3001.Stelle wäre das Null-Zeichen
Narses hat folgendes geschrieben : | Das mit den Xen ist doch etwas schwammig, worum geht´s denn da wirklich, vielleicht gibt´s ja Alternativen. |
ein Beispiel wäre, dass man in einer DLL-Funktion einen SQL-String zusammenbaut, der (je nach Logik) länger oder kürzer sein kann und den SQL-String an die Haupanwendd ng zurückgibt.
bye
Moderiert von Narses: Zitat kenntlich gemacht.
|
|
Narses
      

Beiträge: 10183
Erhaltene Danke: 1256
W10ent
TP3 .. D7pro .. D10.2CE
|
Verfasst: Di 29.06.10 22:13
Moin!
michaelarban hat folgendes geschrieben : | verstehe ich das richtig, dass der Buffer eine Obergrenze haben muss? |
Nun, was heisst "muss"  du forderst ja ein Stück Speicher an, und das hat halt eine bestimmte Größe.
michaelarban hat folgendes geschrieben : | Wenn ich also weiss, dass die Funktion func1 nicht mehr als 1000 Xen zurückliefern wird, kann ich die Buffergröße bspw. auf 3000 setzen: |
Ja, so etwa sollte das laufen.
michaelarban hat folgendes geschrieben : | Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11:
| procedure func1 (pcharInput : PChar; pcharBuffer : PChar) var myString : String; begin myString := gibVieleX(); myString := myString + pcharInput ; if Assigned(pcharBuffer) then StrLCopy(pcharBuffer, PChar(myString), Length(myString)); | |
Hier fehlt natürlich noch die Abfrage, ob der Buffer groß genug ist, heisst: du musst auch die Buffergröße als Parameter durchreichen.
michaelarban hat folgendes geschrieben : | wie sieht dann die String-Variable ergebnis aus, wenn bspw. nur 4 Xen zurückgeliefert wreden:
"gib mir die Xe: XXXX" |
Jup, genau so.
michaelarban hat folgendes geschrieben : | oder so
"gib mir die Xe: XXXXvynbcviuhqp98tflkjh3453409lkgdfgsdfglg pwe96230909tu ....datenmüll bis zur 3000.stelle#0" , 3001.Stelle wäre das Null-Zeichen |
Du hast doch bestimmt mal in die DOH zum Thema StrLCopy geschaut, oder? Und da sollte stehen, dass StrLCopy einen Null-Terminator schreibt.
cu
Narses
_________________ There are 10 types of people - those who understand binary and those who don´t.
|
|
|