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.