Einzelnen Beitrag anzeigen

Benutzerbild von himitsu
himitsu
Online

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
43.155 Beiträge
 
Delphi 12 Athens
 
#9

Re: C++ Dll soll Zeichenkette manipulieren

  Alt 2. Feb 2009, 15:45
ich bin nich so gut in C ... drum hab ich's mal in Delphi gemacht, aber läßt sich bestimmt leicht konvertieren


drei Funktionen welche dann in der C-DLL drin wären
1: versucht 'nen kürzeren String einzutragen
2: versucht 'nen längeren String einzutragen
3: trägt einen String ein, incl. Speichermanagement
Delphi-Quellcode:
  Type PAnsiStringInfo = ^TAnsiStringInfo;
    TAnsiStringInfo = packed Record
      RefCount: LongInt;
      ElementCount: LongInt;
      DataAddr: packed Array[0..0] of AnsiChar;
    End;

  Function _SetString1(PString: PPointer): Boolean; StdCall;
    Var i: Integer;
      S: AnsiString;
      P: PAnsiStringInfo;

    Begin
      SetLength(S, 5);
      For i := 1 to 5 do S[i] := Chr($41 + Random(26));


      P := Pointer(Integer(PString^) - 8);
      If (PString^ <> nil) and (P.RefCount = 1)
          and (P.ElementCount >= Length(S)) Then Begin
        P.ElementCount := Length(S);
        MoveMemory(@P.DataAddr, PAnsiChar(S), Length(S) + 1);
        Result := True;
      End Else Result := False;
    End;

  Function _SetString2(PString: PPointer): Boolean; StdCall;
    Var i: Integer;
      S: AnsiString;
      P: PAnsiStringInfo;

    Begin
      SetLength(S, 10);
      For i := 1 to 10 do S[i] := Chr($41 + Random(26));


      P := Pointer(Integer(PString^) - 8);
      If (PString^ <> nil) and (P.RefCount = 1)
          and (P.ElementCount >= Length(S)) Then Begin
        P.ElementCount := Length(S);
        MoveMemory(@P.DataAddr, PAnsiChar(S), Length(S) + 1);
        Result := True;
      End Else Result := False;
    End;

  Type TDelphiGetMemory = function(Size: Integer): Pointer; CDecl;
       TDelphiFreeMemory = function(P: Pointer): Integer; CDecl;

  Var DelphiGetMemory: TDelphiGetMemory;
      DelphiFreeMemory: TDelphiFreeMemory;

  Procedure SetString3Memory(GetMem: TDelphiGetMemory; FreeMem: TDelphiFreeMemory); StdCall;
    Begin
      DelphiGetMemory := @GetMem;
      DelphiFreeMemory := @FreeMem;
    End;

  Function _SetString3(PString: PPointer): Boolean; StdCall;
    Var i: Integer;
      S: AnsiString;
      P: PAnsiStringInfo;

    Begin
      SetLength(S, 7);
      For i := 1 to 7 do S[i] := Chr($41 + Random(26));


      P := Pointer(Integer(PString^) - 8);
      If S > 'Then Begin
        If (PString^ = nil) or (P.RefCount = -1) Then Begin
        End Else If P.RefCount > 1 Then Begin
          Dec(P.RefCount);
        End Else If P.ElementCount <> Length(S) Then Begin
          DelphiFreeMemory(P);
        End;
        P := DelphiGetMemory(8 + Length(S) + 1);
        P.RefCount := 1;
        P.ElementCount := Length(S);
        MoveMemory(@P.DataAddr, PAnsiChar(S), Length(S) + 1);
        PString^ := Pointer(Integer(P) + 8);
      End Else Begin
        If PString^ <> nil Then
          If P.RefCount = -1 Then
            PString^ := nil
          Else If P.RefCount <> 0 Then Begin
            Dec(P.RefCount);
            If P.RefCount = 0 Then Begin
              DelphiFreeMemory(P);
              PString^ := nil;
            End;
          End;
      End;
      Result := True;
    End;
und die Testaufrufe:
Delphi-Quellcode:
  Var ZweitString: AnsiString;

  Procedure TForm1.FormCreate(Sender: TObject);
    Const BoolStr: Array[Boolean] of String = ('False', 'True ');
      ConstString = '123456789';

    Var S: AnsiString;
      B: Boolean;

    Begin
      Memo1.Lines.Add('');
      Memo1.Lines.Add('Leerstring');
      Memo1.Lines.Add('ConstString');
      Memo1.Lines.Add('String mit Referenzzähler = 1');
      Memo1.Lines.Add('String mit Referenzzähler = 2');

      Memo1.Lines.Add('');
      S := '';
      Memo1.Lines.Add(Format('x1 - False - "%s"', [S]));
      S := ConstString;
      Memo1.Lines.Add(Format('x2 - False - "%s"', [S]));
      SetLength(S, 8);
      Memo1.Lines.Add(Format('x3 - False - "%s"', [S]));
      ZweitString := S;
      Memo1.Lines.Add(Format('x4 - False - "%s"', [S]));

      Memo1.Lines.Add('');
      S := '';
      B := SetString1(S); Memo1.Lines.Add(Format('11 - %s - "%s"', [BoolStr[B], S]));
      S := ConstString;
      B := SetString1(S); Memo1.Lines.Add(Format('12 - %s - "%s"', [BoolStr[B], S]));
      SetLength(S, 8);
      B := SetString1(S); Memo1.Lines.Add(Format('13 - %s - "%s"', [BoolStr[B], S]));
      ZweitString := S;
      B := SetString1(S); Memo1.Lines.Add(Format('14 - %s - "%s"', [BoolStr[B], S]));

      Memo1.Lines.Add('');
      S := '';
      B := SetString2(S); Memo1.Lines.Add(Format('21 - %s - "%s"', [BoolStr[B], S]));
      S := ConstString;
      B := SetString2(S); Memo1.Lines.Add(Format('22 - %s - "%s"', [BoolStr[B], S]));
      SetLength(S, 8);
      B := SetString2(S); Memo1.Lines.Add(Format('23 - %s - "%s"', [BoolStr[B], S]));
      ZweitString := S;
      B := SetString2(S); Memo1.Lines.Add(Format('24 - %s - "%s"', [BoolStr[B], S]));

      Memo1.Lines.Add('');
      SetString3Memory(@GetMemory, @FreeMemory);
      S := '';
      B := SetString3(S); Memo1.Lines.Add(Format('31 - %s - "%s"', [BoolStr[B], S]));
      S := ConstString;
      B := SetString3(S); Memo1.Lines.Add(Format('32 - %s - "%s"', [BoolStr[B], S]));
      SetLength(S, 8);
      B := SetString3(S); Memo1.Lines.Add(Format('33 - %s - "%s"', [BoolStr[B], S]));
      ZweitString := S;
      B := SetString3(S); Memo1.Lines.Add(Format('34 - %s - "%s"', [BoolStr[B], S]));
    End;
Code:
Leerstring
ConstString
String mit Referenzzähler = 1
String mit Referenzzähler = 2

x1 - False - ""
x2 - False - "123456789"
x3 - False - "12345678"
x4 - False - "12345678"

11 - False - ""
12 - False - "123456789"
13 - True - "CMBVB"
14 - False - "CMBVB"

21 - False - ""
22 - False - "123456789"
23 - False - "12345678"
24 - False - "12345678"

31 - True - "CUMWNOY"
32 - True - "RIASZUT"
33 - True - "FDXUPWR"
34 - True - "HCQHWEH"
wie man sieht, geht es nur bedingt.
11 - kein String vorhanden
12 - geht nicht, da Konstante und somit ist kein Speicher reserviert
13 - Sring ist kurz genug und Referenzzählung steht auf 1
14 - Referenzzählug > 1

21 - kein String vorhanden
22 - geht nicht, da Konstante und somit ist kein Speicher reserviert
23 - Referenzzählung steht zwar auf 1, aber einzutragender String ist zu lang
24 - Referenzzählug > 1

Im Endefekt muß man den String auf seine interne Struktur zerlegen und alles selbst verwalten ... es sei denn, einer erfindet 'ne Klasse dafür

bzw. man macht auf _SetString3 eine Prozedur, welcher man zusätzlich noch 'nen C-String übergeben kann, welcher in den Delphi-String kopiert wird.

einzig und allein die 23 liese sich noch ändern, indem alles was länger ist abgeaschnitten wird.
Angehängte Dateien
Dateityp: 7z project1_110.7z (1,7 KB, 2x aufgerufen)
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list : BugReports/FeatureRequests
  Mit Zitat antworten Zitat