Ciao Alka,
sono sempre in ballo con quella famosa DLL che sto sviluppando e ho scoperto che in qualche modo il puntatore utilizzato non si dealloca e alla seconda volta che richiamo la mia funzione, mi ritorna errore EInvalidPointer. Attualmente copio una stringa di tipo string in un puntatore e dalla funzione DLL passo il suo contenuto all'applicativo che ne fa richiesta. Pensavo di modificare la cosa in base ad un tuo suggerimento che mi avevi dato settimane fa, ovvero passare l'indirizzo del puntatore e non il suo contenuto.
Ho capito bene?
Non sono ancora in grado di sfruttare bene i puntatori, devo ancora comprenderli a pieno ma vorrei porre alla tua attenzione il codice utilizzato, sia per la DLL che per l'applicazione che la richiama. Magari sai dirmi dove effettivamente è sbagliato o magari mi puoi dare qualche altro suggerimento.
Funzioni residenti nella DLL (La funzione Polling() richiama la funzione DownloadPolling()):
Questo è il codice dell'applicazionecodice:Function DownloadPolling(IDBOX: Integer): String; var Response : String; Content : array of char; I : Integer; begin //Controllo che l'apertura sia stata correttamente eseguita if ApdComPort1.Open then begin //Invio il carattere EOT di chiusura per evitare trasmissioni aperte precedentemente ApdComPort1.PutString(chr($04)); //Invio la stringa di Polling: [SOH][GID][DID][ENQ] che in esadecimale diventa [01][41][?][05] ApdComPort1.PutString(chr($01)+chr($41)+IntToStr(IDBOX)+chr($05)); //Attivo il timer in modo da controllare il buffer per circa un secondo NewTimer(ET, 4); //Finchè il timer non si azzera controllo se il box mi ha spedito i dati I := 0; SetLength(Content, 104); Response := ''; repeat while ApdComPort1.CharReady do begin Content[I] := ApdComPort1.GetChar; //if I > 5 then //begin //if I in [6..9] then Response := Response+IntToStr(Ord(Content[I])) //else Response := Response+Content[I]; //end; I := I + 1; end; until TimerExpired(ET); for I := 1 to 104 do begin Response := Response+Content[I]; end; Content := Nil; Result := Response; end else begin Result := ''; end; end; Function Polling(DID: PChar): PChar; export; StdCall; var ResponseBox : String; VerifyXor : byte; I : Integer; begin if ApdComPort1 = nil then ApdComPort1 := TApdComPort.Create(nil); try //Configuro la porta seriale e la apro per iniziare le comunicazioni ApdComPort1.ComNumber := 1; ApdComPort1.Baud := 9600; ApdComPort1.Parity := pNone; ApdComPort1.DataBits := 8; ApdComPort1.StopBits := 1; ApdComPort1.InSize := 128; ApdComPort1.Open := true; FreeMem(Result, 105); if ApdComPort1.Open then begin //for N := 1 to Loop do //begin repeat //repeat ResponseBox := DownloadPolling(StrToInt(DID)); //until ResponseBox <> ''; VerifyXor := $00; if ResponseBox <> '' then begin for I := 1 to 104 do begin VerifyXor := VerifyXor xor Byte(ResponseBox[I]); end; //Verifico l'esito del VCR, se 0 è corretto altrimenti c'è stato qualche errore if VerifyXor = 0 then begin //I dati sono corretti e invio la stringa di ritorno che il box si aspetta inviando un ACK = Hex(06) ApdComPort1.PutString(Chr($01) + Chr($41) + Chr($31) + Chr($06)); //Chiudo la trasmissione con EOT ApdComPort1.PutString(Chr($04)); end else begin //I dati sono errati e invio la stringa di ritorno che il box si aspetta inviando un NACK = Hex(15) ApdComPort1.PutString(Chr($01) + Chr($41) + Chr($31) + Chr($15)); //Chiudo la trasmissione con EOT ApdComPort1.PutString(Chr($04)); end; end else begin ResponseBox := 'ERROR'; end; until VerifyXor = 0; //end; //Chiudo la porta di comunicazione ApdComPort1.Open := false; end else begin ResponseBox := 'COM Port Close'; end; //Alloco memoria per contenere il valore di ritorno della funzione da passare al software GetMem(Result,105); //Copio il valore di ritorno nella variabile che la funzione ritorna Result := StrPCopy(Result, ResponseBox); finally ApdComPort1.Free; end; end;
Mi viene un dubbio, se io passo l'indirizzo del puntatore dalla DLL all'applicazione, posso copiare il suo contenuto in una stringa per poi deallocare la memoria del puntatore senza perdere i dati copiati?codice:TextReturn := Polling('1'); //Alloco memoria per contenere il valore di ritorno della funzione da passare al software GetMem(Return,Length(TextReturn)+1); //Copio il valore di ritorno nella variabile che la funzione ritorna Return := StrPCopy(Return, TextReturn); Memo1.Lines.Add(Return); FreeMem(TextReturn, Length(TextReturn)+1)
Grazie

Rispondi quotando
