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()):
codice:
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;
Questo è il codice dell'applicazione
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)
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?
Grazie