AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Programmieren allgemein C++ Dll soll Zeichenkette manipulieren
Thema durchsuchen
Ansicht
Themen-Optionen

C++ Dll soll Zeichenkette manipulieren

Ein Thema von rey003 · begonnen am 1. Feb 2009 · letzter Beitrag vom 7. Feb 2009
Antwort Antwort
Seite 1 von 2  1 2      
Benutzerbild von rey003
rey003

Registriert seit: 31. Aug 2005
Ort: Sachsen ;-)
46 Beiträge
 
Delphi 2006 Architect
 
#1

C++ Dll soll Zeichenkette manipulieren

  Alt 1. Feb 2009, 16:05
Hallo DPler,
ich stehe grade mal wieder voll auf dem Schlauch. Und zwar möchte ich den Zeiger zu einem String an eine in C++ geschriebene DLL übergeben. Dort soll er dann verändert werden.

Mit Zahlen ist das Ganze kein großes Problem, aber bei der Umsetzung mit Zeichenketten scheitert es dann komplett bei mir!
Ich bin C++ Anfänger. Will mich jedoch mal der Herrausforderung stellen ein Teil in eine C++ Dll auszulagern (als Übung).

Hier mal mein Code für Integer:

C++ Dll:
Code:
extern "C" __declspec(dllexport) void Zahl_aendern(int * zahl);

void Zahl_aendern(int * zahl)
{
    *zahl = 50;
}
Aufruf in Delphi:
Delphi-Quellcode:
procedure Zahl_aendern(zahl: PInteger); cdecl; external 'meine_dll.dll';

...

procedure TForm1.Button1Click(Sender: TObject);
var
  i: integer;
begin
  i:= 12;
  showmessage(inttostr(i)); //12
  Zahl_aendern(@i);
  showmessage(inttostr(i)); //50
end;
Das funktioniert perfekt, aber wie gestaltet man das Ganze mit Strings?
Ich hoffe Ihr könnt mir helfen
Daniel S.
  Mit Zitat antworten Zitat
Benutzerbild von Luckie
Luckie

Registriert seit: 29. Mai 2002
37.621 Beiträge
 
Delphi 2006 Professional
 
#2

Re: C++ Dll soll Zeichenkette manipulieren

  Alt 1. Feb 2009, 16:17
In C gibt es keine Zeichenketten, die in Delphi einem String entsprächen. In C gibt es nur Charakter-Arrays. Diese entsprechen in Delphi dem Datentyp PChar. Und dann geht eigentlich alles so wie hier http://www.michael-puff.de/Artikel/StringDLL.shtml beschrieben.

IN C++ gibt es noch die String Klasse, definiert in String.h, glaube ich. In wie fern diese mit den Delphi Stringtyp kompatibel sind kann ich nicht sagen. Ich vermute aber sie sind eher nicht kompatibel.
Michael
Ein Teil meines Codes würde euch verunsichern.
  Mit Zitat antworten Zitat
Benutzerbild von rey003
rey003

Registriert seit: 31. Aug 2005
Ort: Sachsen ;-)
46 Beiträge
 
Delphi 2006 Architect
 
#3

Re: C++ Dll soll Zeichenkette manipulieren

  Alt 1. Feb 2009, 19:41
ja so ungefähr war mir das ganze schon klar auch wenn es ziemlich komplex gemacht ist, aber mir fehlt jegliche vorstellung wie ich es in c++ umsetzen soll.

PChar liefert mir zwar den Zeiger auf den Char-Array, aber ich kann den Inhalt nicht verändern in C++.

Das führt zu folgendem Fehler:
Code:
extern "C" __declspec(dllexport) void String_aendern(char * sstring);

void String_aendern(char ** sstring)
{
   *sstring = "Hallo";
}
error C2440: '=': 'const char [6]' kann nicht in 'char' konvertiert werden

Mir fehlt die Grundlage in C++
Daniel S.
  Mit Zitat antworten Zitat
Benutzerbild von Der Jan
Der Jan

Registriert seit: 22. Dez 2005
289 Beiträge
 
Delphi XE7 Ultimate
 
#4

Re: C++ Dll soll Zeichenkette manipulieren

  Alt 2. Feb 2009, 14:07
Hallo,

erstmal kannst du nicht einmal char* und einmal char** schreiben. char* reicht . Da hast du dann auch die kompatibilität mit dem Delphi PChar.
Dann solltest du den neuen String mittels

Code:
strcpy(sstring, "Hallo");
einkopieren. Dann sollte es gehen. Kann sein, dass Quelle und Ziel vertauscht sind, da musst du mal in der Hilfe schauen, hab ich jetzt nicht im Kopf.

Edit: Die C++Klasse string kommt aus der STL (Standard Template Library oder Standard C++ Library, wie sie heute heißt, trotzdem sagen alle STL ) und ist definitiv nicht kompatibel mit einem Delphi-Stringtyp.
Gruß, Jan
  Mit Zitat antworten Zitat
Benutzerbild von rey003
rey003

Registriert seit: 31. Aug 2005
Ort: Sachsen ;-)
46 Beiträge
 
Delphi 2006 Architect
 
#5

Re: C++ Dll soll Zeichenkette manipulieren

  Alt 2. Feb 2009, 15:00
Der Fehler oben im Quelltext war unbeabsichtigt. Hab ihn im Original auch nicht gehabt.
StrCpy führt immer zu einer Zugriffsverletzung in der DLL (meldet Delphi).
Daniel S.
  Mit Zitat antworten Zitat
Benutzerbild von Der Jan
Der Jan

Registriert seit: 22. Dez 2005
289 Beiträge
 
Delphi XE7 Ultimate
 
#6

Re: C++ Dll soll Zeichenkette manipulieren

  Alt 2. Feb 2009, 15:08
Kommt die AV beim Aufruf oder direkt bei strcpy? Du könntest mal versuchen, die DLL-Funktion direkt aus C aufzurufen, ob das da auch passiert.
Gruß, Jan
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

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

Re: C++ Dll soll Zeichenkette manipulieren

  Alt 2. Feb 2009, 15:28
Wenn der String aka AnsiString verändert werden soll, dann geht das maximal nur dann, wenn der String nicht länger wird und die Referenzzählung auf 1 steht.

Wenn de String länger werden soll, mehr als eine Referenz existiert und bei Konstanten müßte man Speicher reservieren und dazu müßtest du auch noch die Funktionen des Speichermanagers exportieren.


Bei WideString ist es einfacher, da dieser Delphiintern einen OleStr kapselt, welcher auch in C verfügbar wäre.
Neuste Erkenntnis:
Seit Pos einen dritten Parameter hat,
wird PoSex im Delphi viel seltener praktiziert.
  Mit Zitat antworten Zitat
Benutzerbild von sirius
sirius

Registriert seit: 3. Jan 2007
Ort: Dresden
3.443 Beiträge
 
Delphi 7 Enterprise
 
#8

Re: C++ Dll soll Zeichenkette manipulieren

  Alt 2. Feb 2009, 16:10
Einen Delphistring in C zu verändern, das ist ja, wie mit dem Flugzeug zum Bahnhof zu fliegen um dann mit dem Zug nach Mallorca zu fahren.

Wie himitsu schon schreibt, du kannst einen Delphistring nicht in C verändern. Entweder du nimmst einen widestring, oder du präparierst den string vorher um. Dazu musst du ihn in ein array[0..x] of char kopieren (am besten mit "move").
Dieser Beitrag ist für Jugendliche unter 18 Jahren nicht geeignet.
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

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

Re: C++ Dll soll Zeichenkette manipulieren

  Alt 2. Feb 2009, 16: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)
Neuste Erkenntnis:
Seit Pos einen dritten Parameter hat,
wird PoSex im Delphi viel seltener praktiziert.
  Mit Zitat antworten Zitat
Benutzerbild von Der Jan
Der Jan

Registriert seit: 22. Dez 2005
289 Beiträge
 
Delphi XE7 Ultimate
 
#10

Re: C++ Dll soll Zeichenkette manipulieren

  Alt 2. Feb 2009, 17:26
Was mir wegen der AV grad noch eingefallen ist: Reservierst du in deinem Delphiprogramm Speicher für den String?

[OT]
Zitat von sirius:
Einen Delphistring in C zu verändern, das ist ja, wie mit dem Flugzeug zum Bahnhof zu fliegen um dann mit dem Zug nach Mallorca zu fahren.
LOL. Das muss ich mir merken

[\OT]
Gruß, Jan
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2      


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 03:06 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz