Newsgroup: it.comp.lang.delphi
Titolo: Problemi con seriale e puntatori

Ciao a tutti, vi pongo un problema che trovo semplicemente incredibile,
non riesco a trovare il senso di questo comportamento. Spiego
brevemente la situation:
ho creato una DLL con alcune funzioni per connettersi a una porta
seriale e scaricare dati da un'altro PC e il tutto viene pilotato da un
software esterno; la DLL deve essere per forza standard, nel senso che
verrà interfacciata ad altri programmi creati con linguaggi differenti
da delphi e quindi dovrà essere portabile al 100%. Ora, il sorgente è
un po più lungo di questo ma ho semplificato le due funzioni
all'inverosimile per isolare il problema e capire da cosa possa
derivare ma non c'è niente da fare, va contro ogni mia logica, non lo
capisco. Devo aggiungere anche, cosa molto importante, che se dal
software commento la deallocazione del buffer tutto funziona
regolarmente senza nessunissimo problema escludendo il fatto che in
quel modo il programma va in memory leak.
Codice DLL
------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//Funzione che Recupera i dati dalla seriale
Function DownloadPolling(IDBOX: String): String; StdCall;
 var
  Response    : String;
begin
  Response := '';
  if Conn then
    begin
      ApdComPort1.PutString(chr($04));
      ApdComPort1.PutString(chr($01)+chr($41)+IDBOX+chr($05));
      NewTimer(ET, 4);
      repeat
        while ApdComPort1.CharReady do
          begin
            Response := Response+ApdComPort1.GetChar;
          end;
      until TimerExpired(ET);
    end;
    DownloadPolling := Response; ---> QUI ALLA SECONDA CHIAMATA NON
VIENE IMPOSTATO NULLA MA RESPONSE CONTIENE I DATI.
end;
//Funzione richiamata dal software che elabora i dati scaricati
Function Polling(DID: PChar): PChar; export; StdCall;
var
  ResponseBox : String;
begin
  if Conn then
  begin
      repeat
        ResponseBox := DownloadPolling(DID);
      until ResponseBox <> '';
  end
  else
  begin
    ResponseBox := 'ERROR: COM Port Close';
  end;
  GetMem(Result,Length(ResponseBox)+1);
  Result := StrPCopy(Result, ResponseBox);
end;
------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Codice Form del Software
------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Var
  TextReturn: PChar;
begin
  TextReturn := Polling('PIPPO');
  Memo1.Lines.Add(TextReturn);
  FreeMem(TextReturn); ---> Questa parte vorrei farla gestire dalla DLL
con una funzione
end;
------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Ecco quello che succede:
alla prima chiamata della funzione Polling() funziona tutto
regolarmente (richiama la funzione DownloadPolling e gli ritorna il
valore correttamente), alla seconda invece, quando arriva ad eseguire
il codice della funzione DownloadPolling, i dati vengono scaricati
dalla seriale in modo corretto ma non viene assegnato nulla alla
variabile di ritorno. Perchè? Porca pupazza perchè?????
Grazie mille.

       until ResponseBox <> '';
xche, se x qualche motivo ResponseBox non viene mai valorizzata, da qui 
non esci. Ti suggerisco di modificare questo codice introducento un 
numero massimo di tentativi da fare, magari passandolo come parametro.
In questo modo la responsabilita' legata ad una infinita esecuzione del 
loop la sposti dalla dll alla applicazione chiamante, come, imho, e' 
giusto che sia... Una cosa del tipo:
Function Polling(const ATryCount: word; DID, AValue: pchar): integer; 
export; StdCall;
var
   TryCounter: word;
....
         TryCounter := 0;
 >       repeat
           INC(TRYCOUNT);
           IF TRYCOUNT > TRYCOUNT THEN
              BREAK;
 >         ResponseBox := DownloadPolling(DID);
 >       until ResponseBox <> '';
A.

 IF TRYCOUNT > TRYCOUNT THEN
Ti sei distratto un attimo? :-)
-- 
#@!&

 Ti sei distratto un attimo? :-)
il caldo... :-(((
         TryCounter := 0;
 >       repeat
           INC(TRYCOUNT);
           IF TRYCOUNT > TRYCOUNTER THEN


  >       until ResponseBox <> '';
QUI PROBABILMENTE HAI RAGIONE, VEDRÒ DI INSERIRE IL CONTROLLO.
IN OGNI CASO NON RISOLVO IL PROBLEMA CHE HO DESCRITTO NEL PRIMO POST,
ED È QUESTO CHE MI PREME POICHÈ SE NON CAPISCO IL MOTIVO DELLA
MANCATA ASSEGNAZIONE DEI DATI ALLA VARIBILE DI RITORNO DELLA FUNZIONE
DOWNLOADPOLLING() NON POSSO PROSEGUIRE CON IL RESTO DELLA
PROGRAMMAZIONE. IN BASE AL CODICE CHE HO SCRITTO COSA PUÒ PROVOCARE
QUESTO PROBLEMA? MI RENDO CONTO CHE IL CODICE INSERITO NON HA MOLTO
SENSO COSÌ COM'È MA NON POSSO INSERIRLO COMPLETO, SAREBBE TROPPO
LUNGO E INUTILE ALLA RISOLUZIONE DEL PROBLEMA.
IN OGNI CASO GRAZIE DELL'INTERVENTO.

 IN OGNI CASO NON RISOLVO IL PROBLEMA CHE HO DESCRITTO NEL PRIMO POST,
Ok, ma xche non rpvo a fare come ti ho suggerito, passando un pchar
alla funzione come parametro invece di averlo come riusltato della
funzione? 
A.

 Scusa, xche mi urli contro? :-(((
Perdonami, era solo per differenziare la mia risposta dalla tua.

Cioè usare i PChar nella funzione DownloadPolling() sia come parametro
di ingresso che di uscita?

 di ingresso che di uscita?
si, usarlo come parametro e non come result della funzione.
In questo modo, la responsabilita della allocazione e del rilascio
della memoria passa dalla dll alla applicazione, come e' giusto che
sia, imho....
Visto che non vuoi il numero di caratteri, come result della funzione
puoi restituire un valore tipo:
0: tutto ok, ho letto la stringa e te la passo
-1: errore di timeout (vedi trycount e trycounter nella mia precedente
risposta
-2: errore indefinito
etc etc etc
A.