Announcement

Collapse
No announcement yet.

Delphi 2 - PChar als Parameter oder Funktionsergebnis

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • Delphi 2 - PChar als Parameter oder Funktionsergebnis

    Ich hab Delphi 2.0 Developer und möchte eine DLL erstellen, die einen Textwert zurückgibt.<br>Wenn ich auf "Datei/Neu/DLL" gehe, wird in die neu angelegte DLL automatisch die Bemerkung hinzugefügt, dass man string-Parameter oder string-Funktionsergebnisse nur dann bei DLLs verwenden könne, wenn man Delphimm.dll mit der DLL mitliefert. Wenn man darauf keine Lust habe, solle man nicht string-Werte, sondern PChar-Werte nehmen.<br>OK, dachte ich mir, nehm' ich halt PChar-Werte. Die DLL, die ich erstellen will, soll eine Schach-KI ersetzen. Der Rückgabewert beträgt z.B. "e7-e6".<br>Jetzt stürzt mein Programm beim Aufruf der DLL aber ab, und als ich es debugt habe, ist mir aufgefallen, dass der Rückgabewert nicht wie erwartet "e7-e6" lautet, sondern "e7-e[unbekannte Zeichenfolge]".<br>Weiß jemand, woran das liegt?<br>Ich habe schon versucht, die Funktion aus der DLL herauszunehmen, und so in mein Programm zu implementieren. Solange der Debugger in der Funktion ist, heißt der Rückgabewert (Result) "e7-e6". Sobald aber die Funktion verlassen wird, und in der nächsten Funktion als Parameter verwendet wird, heißt der Parameter wieder "e7-e...".<p>Falls jemand schon einmal dieses Problem hatte, oder vielleicht auch so weiß, woran das liegt, bitte ich Ihn, so schnell wie möglich zu antworten.<br>thx schonmal, Sebastian Meßmer

  • #2
    Muss der Rückgabe wert denn unbedingt ein String sein? Wie wäre es denn stattdessen mit einem Record a la
    <pre>
    <code><font size=3 face="Courier New"><span style="background-color: #FFFFFF"><font color="#000000"><b>type
    </b>TZug = <b>record
    </b>VonX, VonY, NachX, NachY: Byte;
    <b>end</b>;
    </span></font>
    </code></pre>
    Das wäre schneller, einfacher (da keine Probleme mit Stringübergabe :-P), programmatisch leichter auszuwerten usw. usf.
    <br>Uli

    Comment


    • #3
      Danke. Damit ist mein Problem gelöst.<br>Aber mal ganz allgemein: Da muss doch irgend ein Fehler drin sein, wenn das nicht funktioniert. Und wenn ich mal eine DLL mache, bei der es wirklich ein string(bzw. PChar)-Rückgabewert sein muss, stehe ich wieder vor dem gleichen Problem.<br>
      Weiß jemand, woran dieses Problem liegen könnte?<p>thx schonmal, Sebastian Meßme

      Comment


      • #4
        Woher kriegst du den Speicherplatz für den String, auf den der PChar zeigt? Zeig doch mal die Definition der Funktion in der DLL und den Funktionsaufruf im exe.
        <p>Uli

        Comment


        • #5
          <pre>
          Definition:
          function BesterZug(Stellung:[Eigener Typ]):PChar;exports;

          export BesterZug name 'KI';

          Aufruf:

          var DLL:THandle
          KI:function(Stellung:[Eigener Typ]):PChar;
          begin
          DLL:=LoadLibrary(...);
          KI:=getProcAddress(DLL,'KI');
          Result:=KI;
          end;
          </pre&gt

          Comment


          • #6
            Und wie legst du den String innerhalb von KI an? Gibst du die Adresse einer lokalen Arrayvariablen zurück? Oder legst du ihn mit StrNew o.ä. an

            Comment


            • #7
              Mit<p>Result:=PChar(Startfeld+Zielfeld);<br><br>P. S.: "Startfeld" und "Zielfeld" sind string-Variable

              Comment


              • #8
                Das ist nicht so toll. Die Verkettung "Startfeld+Zielfeld" erzeugt dir eine temporäre Stringvariable. Deren Adresse weist du auf Result zu. Nachdem die Zuweisung abgearbeitet ist, wird der temporäre String ad acta gelegt und Result zeigt auf einen ungültigen Speicherbereich. ==> Patsch.
                <p>Wenn du einen PChar zurückgeben willst, solltest du ihn mit StrNew (oder ähnlichem) anlegen. Dann darf der Empfänger aber nicht vergessen, ihn wieder aufzuräumen, das aber nicht einfach direkt mit StrDispose, sondern mit einer Routine in deiner DLL, die StrDispose aufruft, weil ein StrNew in der DLL ein anderen Heap benutzt als ein StrNew in der exe. Du siehst, das mit den PChars + DLLs ist nicht wirklich einfach. :-

                Comment


                • #9
                  Ähm...Hast du Beispielcode

                  Comment


                  • #10
                    Hallo,

                    im Gegensatz zu StrNew (etc.) ist ein <b>array of Char</b> ungefährlicher, solange immer nur ein Thread gleichzeitig auf diese DLL zugreift. Die DLL-Funktion gibt für den PChar-Rückgabewert nur die Adresse (<b>@</b>) der Puffervariable zurück:
                    <pre>
                    <b>library</b> DelphiDLL;
                    <br>
                    <b>uses</b>
                    SysUtils, Classes, Windows;
                    <br>
                    <font color="#003399"><i>{$R *.res}</i></font>
                    <br>
                    <b>var</b>
                    szUserName : <b>array</b>[0..99] <b>of</b> Char;
                    <br>
                    <b>function</b> OSGetUserName: PChar; <b>stdcall</b>;
                    <b>var</b>
                    dwLen : DWORD;
                    <b>begin</b>
                    dwLen := SizeOf(szUserName);
                    FillChar(szUserName, dwLen, #0);
                    GetUserName(szUserName, dwLen);
                    Result := @szUserName;
                    <b>end</b>;
                    <br>
                    <b>exports</b>
                    OSGetUserName <b>index</b> 1;
                    <br>
                    <b>begin</b>
                    <b>end</b>.
                    </pre&gt

                    Comment


                    • #11
                      Heißt das, dass PChar nur ein Pointer ist (P[ointer]Char)

                      Comment


                      • #12
                        Genau. Alles drumherum, was aus dem nackten Zeiger einen String macht (Speicherverwaltung,
                        "tiefe" Kopien etc.), musst du selber in die Hand nehmen, u.U. mit Hilfe von Bibliotheksroutinen (StrNew, StrLen, ...).
                        <p>Uli

                        Comment


                        • #13
                          Naja...Ich glaub', ich mach's doch lieber (wie du am Anfang vorgeschlagen hast) mit einem neuen Typ.

                          Danke,
                          Sebastian Meßme

                          Comment

                          Working...
                          X