AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Sprachen und Entwicklungsumgebungen Sonstige Fragen zu Delphi realloc in C-Dll schlägt fehl bei Aufruf von Delphi IDE
Thema durchsuchen
Ansicht
Themen-Optionen

realloc in C-Dll schlägt fehl bei Aufruf von Delphi IDE

Ein Thema von Mastersargon · begonnen am 18. Dez 2009 · letzter Beitrag vom 19. Dez 2009
Antwort Antwort
Benutzerbild von Mastersargon
Mastersargon

Registriert seit: 18. Dez 2009
4 Beiträge
 
Delphi 7 Enterprise
 
#1

realloc in C-Dll schlägt fehl bei Aufruf von Delphi IDE

  Alt 18. Dez 2009, 18:24
Hallo zusammen,

ich verwende eine in C geschriebene DLL, bei der ich Probleme mit einer Funktion habe:

unsigned char* send(const unsigned long int* data_len, const unsigned char* data, unsigned long int* packet_len, unsigned char* packet);

Aufruf in Delphi:

FUNCTION send({CONST} VAR data_len: DWord; {CONST} data: PChar; VAR packet_len: DWord; packet: PChar): PChar cdecl; external 'test.dll' name 'send';

Grundsätzliche Funktionsweise: Es wird ein Bytefeld 'data' der Länge 'data_len' übergeben. Daraus erstellt die Funktion ein mehr als doppelt so langes Bytefeld 'packet' der Länge 'packet_len'. Dafür muß der Speicher in der Funktion natürlich angepasst werden, weshalb das Feld von 'packet', dessen Adresse vorher schon initialisiert wurde, mit 'realloc' verlängert wird. Zunächst betragen die Längen testweise max. 20 Bytes.

Im C-Testprogramm klappt es. In Delphi nur, wenn ich vor dem Aufruf genug Speicher alloziere und das Programm nicht in der IDE starte - ansonsten erscheint nur das CPU-Debuggerfenster und die Reallokation in der DLL schlägt fehl!

Die Komplementärfunktion 'receive', die ähnlich aufgebaut ist, jedoch ein kürzeres Ergebnis liefert, läuft anstandslos...

Ich verwende Windows XP SP3 und Delphi 7.1 Enterprise. 'Sharemem' oder ähnliches kommt nicht zum Einsatz. Woran könnte es liegen? Warum klappt die Reallokation in der DLL nicht?

Für Ideen oder Lösungsansätze wäre ich dankbar!

Grüße!
  Mit Zitat antworten Zitat
Astat

Registriert seit: 2. Dez 2009
Ort: München
320 Beiträge
 
Lazarus
 
#2

Re: realloc in C-Dll schlägt fehl bei Aufruf von Delphi IDE

  Alt 18. Dez 2009, 21:24
Hallo Mastersargon.

Zitat von Mastersargon:
unsigned char* send(const unsigned long int* data_len, const unsigned char* data, unsigned long int* packet_len, unsigned char* packet);

Aufruf in Delphi:

FUNCTION send({CONST} VAR data_len: DWord; {CONST} data: PChar; VAR packet_len: DWord; packet: PChar): PChar cdecl; external 'test.dll' name 'send';
Versuchs mal mit folgender Deklaration.

Delphi-Quellcode:
  
  function send(data_len: PLongInt; data: PByte;
    var packet_len: LongInt; var packet: Byte): PByte; cdecl;
      external 'test.dllname 'send';
lg. Astat
Lanthan Astat
06810110811210410503210511511603209711003210010110 9032084097103
03211611111604403209711003210010110903210010510103 2108101116122
11610103209010110510810103206711110010103210511003 2068101108112
10410503210310111509910411410510109810111003211910 5114100046
  Mit Zitat antworten Zitat
Benutzerbild von Mastersargon
Mastersargon

Registriert seit: 18. Dez 2009
4 Beiträge
 
Delphi 7 Enterprise
 
#3

Re: realloc in C-Dll schlägt fehl bei Aufruf von Delphi IDE

  Alt 18. Dez 2009, 23:30
Hallo Astat!

Danke für Deine schnelle Antwort! Dein Vorschlag ist in der Tat eine äquivalente Alternative, nur leider besteht das gleiche Problem fort. Der Char (packet) wird angelegt, dessen Adresse (richtig) übergeben, aber eine Speichervergrößerung zum Char-Reihung scheitert...

Die data_len / packet_len Variablen (ob DWord, LongInt oder LongWord bzw. Zeiger darauf - je nach Aufruf) werden korrekt angenommen und verarbeitet. Die Frage ob Byte oder Char: das ist nur eine Darstellungsfrage.
Zusätzlich habe ich in der C-Funktion dafür gesorgt, daß die Speichergröße von packet um 1 größer als packet_len ist und das letzte Zeichen ein #0 ist, um bei einem typecast mit PChar() nicht auf die Nase zu fallen.
Auch Die Zeigeradressen von packet vor und nach der Reallokation sind gleich, sofern ich vorher schon genügend alloziere und nicht in der IDE starte... Überhaupt frage ich mich, warum mit Start in der IDE solche Probleme entstehen können. Kann es sein, daß Delphi ein "Hineinpfuschen" nicht gerne sieht?

Hier der Ausschnitt der C-Funktion:

Code:

// ...

typedef unsigned char byte; // 8 Bit, unsigned
typedef unsigned short word; // 16 Bit, unsigned
typedef unsigned long int dword; // 32 Bit, unsigned

// ...

// Globale Variable:

dword preamblelen = 6; // Zum Beispiel...

// ...

__declspec (dllexport) byte* send(const dword* data_len, const byte* data, dword* packet_len, byte* packet) {
  dword lc;
  word coded_;
  word* coded = &coded_;
  *packet_len = preamblelen + 1 + *data_len * 2;
  // 3 Zeilen für Debuging   
  // char msg[100];
  // sprintf(msg, "dl = %d, pl = %d, adr(d) = 0x%x, adr(p) = 0x%x, d = %s, p = %s", *data_len, *packet_len, data, packet, data, packet);
  // MessageBox (0, msg, "2", MB_ICONINFORMATION);
  packet = (byte*) realloc(packet, (*packet_len + 1) * sizeof(byte)); // <---------------- Dies ist die kritische Stelle
  if (packet == NULL) {
    // MessageBox (0, "Reallocation of Memory failed!\n", "Error!", MB_ICONINFORMATION);
    exit(EXIT_FAILURE);
  }
  else { 
    // ... // soweit kommt es nicht mehr...
  }
}
Dieser Code (Delphi Testprogramm) funktioniert - wie gesagt, jedoch nicht wenn er in der IDE gestartet wird:

Delphi-Quellcode:

// Globale Variablen:

  dl, pl : LongWord;
  ds, ps : ShortString;
  dc, pc : Char;
  dpc, ppc : PChar;
  preamble_len: LongWord; // Im Quelltext mit einem konstanten Wert initialisiert

// ...

PROCEDURE TForm1.Button1Click(Sender: TObject);
BEGIN
  dl := Length(Edit1.Text); // In Edit 1 steht: 'Edit1'
  pl := preamble_len + 2 + dl * 2; // Precalculate size of packet length
  ds := Edit1.Text;
  dpc := PChar(ds);
  ppc := AllocMem(pl); // Wenn ich hier nicht bereits den Speicher alloziere, klappt es nicht :(
  //ppc := dummy(dl, dpc, pl, ppc);
  ppc := dcpml_send(dl, dpc, pl, ppc); // bei der alten Deklaration, siehe 1. Post oben
  ps := String(ppc);
  Edit2.Text := ps;
END;
Übrigens habe ich die fragliche Funktion im Prinzip (als dummy-Funktion) in Delphi nachgebildet und dort auch ReallocMem genutzt. Da klappt es ohne weiteres...

Jetzt müßte ich nur noch herausfinden, wie es ohne vorherige Allokation in Delphi geht...

Grüße!
  Mit Zitat antworten Zitat
Astat

Registriert seit: 2. Dez 2009
Ort: München
320 Beiträge
 
Lazarus
 
#4

Re: realloc in C-Dll schlägt fehl bei Aufruf von Delphi IDE

  Alt 19. Dez 2009, 00:27
Hallo Mastersargon.

Wenn packet hier
ppc := nil; //-- AllocMem(pl); // Wenn ich hier nicht bereits den Speicher alloziere, klappt es nicht :( zugewiesen wird, sollte ja realloc wie malloc arbeiten.

packet = (byte*) realloc(packet, (*packet_len + 1) * sizeof(byte)); Wird dies, bei (ppc := nil noch korrekt in der c-Library allociert, oder kracht es hier wieder?

Wenn Ja, was passiert wenn Du folgendes versuchst.

packet = (byte*) realloc(packet, 100); ist dann packet allocation möglich?

lg. Astat
Lanthan Astat
06810110811210410503210511511603209711003210010110 9032084097103
03211611111604403209711003210010110903210010510103 2108101116122
11610103209010110510810103206711110010103210511003 2068101108112
10410503210310111509910411410510109810111003211910 5114100046
  Mit Zitat antworten Zitat
Benutzerbild von Mastersargon
Mastersargon

Registriert seit: 18. Dez 2009
4 Beiträge
 
Delphi 7 Enterprise
 
#5

Re: realloc in C-Dll schlägt fehl bei Aufruf von Delphi IDE

  Alt 19. Dez 2009, 00:50
Vielen herzlichen Dank, Astat!

Der Tipp mit dem Initialisieren des Zeigers mit nil hat's gebracht! Jetzt läuft alles super!

Hätte zwar mit einem bereits auf eine konkrete Speicherstelle verweisenden Zeiger auch funktionieren sollen/müssen(?) - wie eben in C - aber das ist doch auch eine saubere Lösung!


Nochmals vielen Dank!

P.S.: 07811109910403210511511603210010510103210810111612 21161010320901011051081010321101050991041160321031 01115099104114105101098101110033
  Mit Zitat antworten Zitat
Benutzerbild von sx2008
sx2008

Registriert seit: 15. Feb 2008
Ort: Baden-Württemberg
2.332 Beiträge
 
Delphi 2007 Professional
 
#6

Re: realloc in C-Dll schlägt fehl bei Aufruf von Delphi IDE

  Alt 19. Dez 2009, 01:00
Zitat von Mastersargon:
Dafür muß der Speicher in der Funktion natürlich angepasst werden, weshalb das Feld von 'packet', dessen Adresse vorher schon initialisiert wurde, mit 'realloc' verlängert wird. Zunächst betragen die Längen testweise max. 20 Bytes.
Warum so umständlich mit realloc?
Bei Benützung von DLLs ist es üblich (und notwendig) den Speicher vorher zu reservieren.
Delphi-Quellcode:
var
  data:string;
  data_len : integer;
  packet : string;
  packet_len : integer;
begin
  data := 'Testdaten...x';
  data_len := Length(data);
  packet_len := 2 * data_len; // es wird die doppelte Länge erwartet
  SetLength(packet, packet_len); // Speicher reservieren
  send(data_len, PChar(data), packet_len, PChar(packet)); // funktion aufrufen
  // Ergebnis ist in packet
Wenn man vorher nicht weiss, wieviel Speicher das Ziel benötigt ist es üblich, die Funktion zweimal aufzurufen.
Diese Technik wird in der Window API öfter verwendet.
Die DLL-Funktion berechnet dann lediglich die benötigte Länge und schreibt natürlich nicht auf den Zielpuffer (der ja nil ist).
Delphi-Quellcode:
begin
  data := 'Testdaten...x';
  data_len := Length(data);
  packet_len := 0;
  send(data_len, PChar(data), packet_len, nil); // funktion aufrufen, Zielpuffer ist nil
  // die benötigte Länge steht jetzt in packet_len
  SetLength(packet, packet_len); // Speicher reservieren
  send(data_len, PChar(data), packet_len, PChar(packet)); // nochmal aufrufen, diesmal mit Zielpuffer und korrekter Länge
Ich verwende sehr gerne AnsiStrings als Puffer; das ist sehr bequem und Delphi-like.
fork me on Github
  Mit Zitat antworten Zitat
Benutzerbild von Mastersargon
Mastersargon

Registriert seit: 18. Dez 2009
4 Beiträge
 
Delphi 7 Enterprise
 
#7

Re: realloc in C-Dll schlägt fehl bei Aufruf von Delphi IDE

  Alt 19. Dez 2009, 01:18
Hallo sx2008,

die Methode mit dem zweifachen Aufruf war mir zwar auch bekannt, ich habe mich wohl waber zu sehr auf den Delphi-Code fixiert und nicht an ein Redesign der C-Funktion gedacht.
Reallokation funktioniert jetzt ja aber auch.

Danke für Deinen Beitrag!
  Mit Zitat antworten Zitat
Muetze1
(Gast)

n/a Beiträge
 
#8

Re: realloc in C-Dll schlägt fehl bei Aufruf von Delphi IDE

  Alt 19. Dez 2009, 01:46
Man sollte sich vor allem ins Gedächtnis rufen, dass der Speichermanager in der DLL nichts vom Speichermanager deiner Delphi Anwendung weiß. Von daher kann der DLL Speichermanager nicht einen Block realloziieren welcher nicht von ihm verwaltet wird (sondern vom Delphi Speichermanager). Auch wenn er es vllt. frecher weise trotzdem macht hilft es keinem, da dann nach der Rückkehr der Delphi Speichermanager nichts mit der neuen Adresse anfangen kann, da diese nicht von ihm verwaltet wird.

Schon allein aufgrund dieses Hintergrundes muss eine strikte Trennung vollzogen werden und dann leuchtet einem auch der Zwang zu der Verwaltung wie in der WinAPI (exklusive ShellAPI) genutzt ein.
  Mit Zitat antworten Zitat
Antwort Antwort


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 14:39 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