PDA

Visualizza la versione completa : [DELPHI]: Creazione oggetti e assegnazione eventi


colde
20-07-2006, 17:09
Ciao Alka,
finalmente sono riuscito a creare i miei oggetti nella DLL direttamente da codice, ti inserisco comunque il sorgente in modo che tu possa controllarlo e dirmi se ci sono errori di concetto. Ti assicuro che tutto il codice inserito non è frutto di immaginazione o tentativi come facevo fino a poco tempo fa, oggi ho avuto l'illuminazione e quello che ho scritto l'ho capito. Il problema principale ora è capire come gestire gli eventi, questo ancora mi è ignoto anche se un'idea ce l'avrei, in più quando chiudo il form dopo aver richiamato la funzione Connect() e DownloadPollingNEW() (e nient'altro) mi da errore di access violation. Puoi fare luce nel buio della mia mente?

Il codice di base della DLL è questo:


type
TPortCom = class //creo una nuova classe
ApdDataPacket1: TApdDataPacket; //assegno alla classe l'oggetto figlio
ApdComPort1: TApdComPort; //assegno alla classe l'oggetto figlio
public
constructor Create(AOwner: TComponent); //assegno il costruttore
destructor Destroy; override; //assegno il distruttore
procedure ApdDataPacket1StringPacket(Sender: TObject; Data: string); //assegno l'evento che però non funziona
end;

constructor TPortCom.Create(AOwner: TComponent); //procedura richiamata dal costruttore al comando TPortCom.Create()
begin
ApdComPort1 := TApdComPort.Create(nil); //creo l'oggetto ApdComPort1
ApdDataPacket1 := TApdDataPacket.Create(nil); //creo l'oggetto ApdDataPacket1
end;

destructor TPortCom.Destroy; //procedura richiamata per la distruzione della classe
begin
FreeAndNil(PortCom.ApdComPort1); //libero la memoria di ApdComPort1
FreeAndNil(PortCom.ApdDataPacket1); //libero la memoria di ApdDataPacket1
ApdComPort1.Destroy; //distruggo l'oggetto
ApdDataPacket1.Destroy; //distruggo l'oggetto
end;

procedure TPortCom.ApdDataPacket1StringPacket(Sender: TObject; Data: string);
begin
Prova := Trim(Data);
end;

Function DownloadPollingNEW(ADD: PChar; IDBOX: PChar): PChar; export; StdCall;
var
Response : String;
VerifyXor : Byte;
I : Integer;
begin
FreeAndNil(Response);
Try
//Invio il carattere EOT di chiusura per evitare trasmissioni aperte precedentemente
PortCom.ApdComPort1.PutString(chr($04));
//Invio la stringa di Polling: [SOH][GID][DID][ENQ] che in esadecimale diventa [01][41][?][05]
PortCom.ApdComPort1.PutString(chr($01)+ADD+IDBOX+c hr($05));
PortCom.ApdDataPacket1.ComPort := PortCom.ApdComPort1;
PortCom.ApdDataPacket1.StartCond := scString;
PortCom.ApdDataPacket1.StartString := #2;
PortCom.ApdDataPacket1.EndCond := [ecString];
PortCom.ApdDataPacket1.EndString := #3+'?';
//Alloco memoria per contenere il valore di ritorno della funzione da passare al software
if Prova <> '' then
Response := Prova
else
Response := 'Nessun dato';
GetMem(Result,Length(Response));
//Copio il valore di ritorno nella variabile che la funzione ritorna
Result := StrPCopy(Result, Response);
//Result := PChar(Response);
Except
//Alloco memoria per contenere il valore di ritorno della funzione da passare al software
GetMem(Result,StrLen('ERROR'));
//Copio il valore di ritorno nella variabile che la funzione ritorna
Result := StrPCopy(Result, 'ERROR');
end;
end;

Procedure Connect(Baud: PChar; COM: PChar) export; StdCall; //Procedura richiamata dal software esterno
begin
PortCom := TPortCom.Create(nil); //Creo la classe e i suoi oggetti
try
//Configuro la porta seriale e la apro per iniziare le comunicazioni
PortCom.ApdComPort1.ComNumber := StrToInt(COM);
PortCom.ApdComPort1.Baud := StrToInt(Baud);
PortCom.ApdComPort1.Parity := pNone;
PortCom.ApdComPort1.DataBits := 8;
PortCom.ApdComPort1.StopBits := 1;
PortCom.ApdComPort1.InSize := 256;
PortCom.ApdComPort1.Open := true;
Conn := true;
except
FreeAndNil(PortCom.ApdComPort1);
end;
end;

Procedure Disconnect() export; StdCall;
begin
PortCom.ApdComPort1.open := false;
FreeAndNil(PortCom.ApdComPort1);
FreeAndNil(PortCom.ApdDataPacket1);
Conn := false;
end;


Grazie

colde
21-07-2006, 09:38
Dunque, mi ero dimenticato di inserire il riferimento all'evento di ApdDataPacket.OnPacket così ho inserito:

PortCom.ApdDataPacket1.OnPacket := PortCom.ApdDataPacket1Packet;

Ora la funzione DownloadPollingNEW() risulta così:

Function DownloadPollingNEW(ADD: PChar; IDBOX: PChar): PChar; export; StdCall;
var
Response : String;
VerifyXor : Byte;
I : Integer;
begin
FreeAndNil(Response);
Try
//Invio il carattere EOT di chiusura per evitare trasmissioni aperte precedentemente
PortCom.ApdComPort1.PutString(chr($04));
//Invio la stringa di Polling: [SOH][GID][DID][ENQ] che in esadecimale diventa [01][41][?][05]
PortCom.ApdComPort1.PutString(chr($01)+ADD+IDBOX+c hr($05));
PortCom.ApdDataPacket1.ComPort := PortCom.ApdComPort1;
PortCom.ApdDataPacket1.StartCond := scString;
PortCom.ApdDataPacket1.StartString := #2;
PortCom.ApdDataPacket1.EndCond := [ecString];
PortCom.ApdDataPacket1.EndString := #3+'?';
PortCom.ApdDataPacket1.OnPacket := PortCom.ApdDataPacket1Packet; <--- EVENTO
//Alloco memoria per contenere il valore di ritorno della funzione da passare al software
if Prova <> '' then
Response := Prova
else
Response := 'Nessun dato';
GetMem(Result,Length(Response));
//Copio il valore di ritorno nella variabile che la funzione ritorna
Result := StrPCopy(Result, Response);
//Result := PChar(Response);
Except
//Alloco memoria per contenere il valore di ritorno della funzione da passare al software
GetMem(Result,StrLen('ERROR'));
//Copio il valore di ritorno nella variabile che la funzione ritorna
Result := StrPCopy(Result, 'ERROR');
end;
end;


Però non lo rileva comunque, mi sai dire dove sbaglio? Mi sembra che sia corretto ma evidentemente c'è qualcosa di sbagliato nella dichiarazione del Type, credo che dipenda da quello.
Grazie

alka
21-07-2006, 09:44
Non è chiaro cosa sia PortCom... :master:

colde
21-07-2006, 09:47
Perchè? E' la classe principale che mi serve per poter utilizzare i due componenti ApdComPort e ApdDataPacket. E' sbagliato? :( Vuoi dire che non ho capito una fava e mi sono montato solo castelli di sabbia?

alka
21-07-2006, 10:43
Originariamente inviato da colde
Perchè? E' la classe principale che mi serve per poter utilizzare i due componenti ApdComPort e ApdDataPacket. E' sbagliato? :( Vuoi dire che non ho capito una fava e mi sono montato solo castelli di sabbia?
No, non ricordavo la presenza del codice sopra. Ma quel codice (quello del primo messaggio) è ancora quello attuale? :master:

colde
21-07-2006, 11:02
Non ho ben capito la tua domanda ma ti riposto il codice per intero con l'aggiunta dell'assegnazione dell'evento alla procedura.



type
TPortCom = class(TObject)
ApdDataPacket1: TApdDataPacket;
ApdComPort1: TApdComPort;
public
constructor Create(AOwner: TComponent);
destructor Destroy; override;
procedure ApdDataPacket1Packet(Sender: TObject; Data: Pointer; Size: Integer);
end;

var
PortCom : TPortCom;
ET : EventTimer;
Conn : Boolean;
Prova : PChar;

constructor TPortCom.Create(AOwner: TComponent);
begin
ApdComPort1 := TApdComPort.Create(nil);
ApdDataPacket1 := TApdDataPacket.Create(nil);
end;

destructor TPortCom.Destroy;
begin
ApdComPort1.Open := false;
FreeAndNil(ApdComPort1);
FreeAndNil(ApdDataPacket1);
ApdComPort1.Destroy;
ApdDataPacket1.Destroy;
end;

procedure TPortCom.ApdDataPacket1Packet(Sender: TObject; Data: Pointer; Size: Integer);
begin
Prova := Data;
end;

Function DownloadPollingNEW(ADD: PChar; IDBOX: PChar): PChar; export; StdCall;
var
Response : String;
VerifyXor : Byte;
I : Integer;
begin
FreeAndNil(Response);
Try
//Invio il carattere EOT di chiusura per evitare trasmissioni aperte precedentemente
PortCom.ApdComPort1.PutString(chr($04));
//Invio la stringa di Polling: [SOH][GID][DID][ENQ] che in esadecimale diventa [01][41][?][05]
PortCom.ApdComPort1.PutString(chr($01)+ADD+IDBOX+c hr($05));
PortCom.ApdDataPacket1.ComPort := PortCom.ApdComPort1;
PortCom.ApdDataPacket1.StartCond := scString;
PortCom.ApdDataPacket1.StartString := #2;
PortCom.ApdDataPacket1.EndCond := [ecString];
PortCom.ApdDataPacket1.EndString := #3+'?';
PortCom.ApdDataPacket1.OnPacket := PortCom.ApdDataPacket1Packet;
//Alloco memoria per contenere il valore di ritorno della funzione da passare al software
if Prova <> '' then
Response := Prova
else
Response := 'Nessun dato';

GetMem(Result,Length(Response));
//Copio il valore di ritorno nella variabile che la funzione ritorna
Result := StrPCopy(Result, Response);
//Result := PChar(Response);
Except
//Alloco memoria per contenere il valore di ritorno della funzione da passare al software
GetMem(Result,StrLen('ERROR'));
//Copio il valore di ritorno nella variabile che la funzione ritorna
Result := StrPCopy(Result, 'ERROR');
end;
end;

Procedure Connect(Baud: PChar; COM: PChar) export; StdCall;
var Creato: String;
begin
PortCom := TPortCom.Create(nil);
try
//Configuro la porta seriale e la apro per iniziare le comunicazioni
PortCom.ApdComPort1.ComNumber := StrToInt(COM);
PortCom.ApdComPort1.Baud := StrToInt(Baud);
PortCom.ApdComPort1.Parity := pNone;
PortCom.ApdComPort1.DataBits := 8;
PortCom.ApdComPort1.StopBits := 1;
PortCom.ApdComPort1.InSize := 256;
PortCom.ApdComPort1.Open := true;
Conn := true;
except
FreeAndNil(PortCom.ApdComPort1);
end;
end;

Procedure Disconnect() export; StdCall;
begin
PortCom.ApdComPort1.open := false;
FreeAndNil(PortCom.ApdComPort1);
FreeAndNil(PortCom.ApdDataPacket1);
Conn := false;
end;

alka
21-07-2006, 11:39
var
Response : String;

...
FreeAndNil(Response);


:oVVoVe: :confused:

colde
21-07-2006, 11:59
Ops non mi sono accorto, era un rimasuglio del vecchio codice per tentare di capire perchè si bloccava a metà la ricezione dei dati da seriale. Ho pensato che magari rimaneva del testo per qualche errore e la lunghezza dei dati superava la lunghezza massima della stringa ma non era così. Non sono riuscito a capire il motivo di quel comportamento, era per questo che al secondo ciclo di download dei dati si impiantava e mi dava access violation; ad un certo punto dopo una trentina di caratteri scaricati mi diceva che il processo non era più valido. Forse era la procedura di scarico dati che utilizzavo che non era ottimale per le mie necessità ed è per quel motivo che ora sto provando a usare il datapacket e non il getchar.
Va bhe ora ho eliminato quella parte ma comunque non mi assegna l'evento alla procedura che gli ho indicato. Il problema rimane. L'invio della richiesta da DLL a seriale sono sicuro che funziona perchè il PC vede la richiesta e in teoria mi manda la risposta con i dati richiesti ma non si attiva l'evento per il recupero.

colde
21-07-2006, 18:20
UP!! :bhò: Niente da fare, l'evento non viene associato.



type
TPortCom = class(TObject)
ApdDataPacket1: TApdDataPacket;
ApdComPort1: TApdComPort;
public
constructor Create(AOwner: TComponent);
destructor Destroy; override;
procedure ApdDataPacket1Packet(Sender: TObject; Data: Pointer; Size: Integer);
end;

var
PortCom : TPortCom;
ET : EventTimer;
Conn : Boolean;
Prova : PChar;

constructor TPortCom.Create(AOwner: TComponent);
begin
ApdComPort1 := TApdComPort.Create(nil);
ApdDataPacket1 := TApdDataPacket.Create(nil);
end;

destructor TPortCom.Destroy;
begin
ApdComPort1.Open := false;
FreeAndNil(ApdComPort1);
FreeAndNil(ApdDataPacket1);
ApdComPort1.Destroy;
ApdDataPacket1.Destroy;
end;

procedure TPortCom.ApdDataPacket1Packet(Sender: TObject; Data: Pointer; Size: Integer);
begin
Prova := Data;
end;

Function DownloadPollingNEW(ADD: PChar; IDBOX: PChar): PChar; export; StdCall;
var
Response : String;
VerifyXor : Byte;
I : Integer;
begin
Try
//Invio il carattere EOT di chiusura per evitare trasmissioni aperte precedentemente
PortCom.ApdComPort1.PutString(chr($04));
//Invio la stringa di Polling: [SOH][GID][DID][ENQ] che in esadecimale diventa [01][41][?][05]
PortCom.ApdComPort1.PutString(chr($01)+ADD+IDBOX+c hr($05));
PortCom.ApdDataPacket1.ComPort := PortCom.ApdComPort1;
PortCom.ApdDataPacket1.StartCond := scString;
PortCom.ApdDataPacket1.StartString := #2;
PortCom.ApdDataPacket1.EndCond := [ecString];
PortCom.ApdDataPacket1.EndString := #3+'?';
PortCom.ApdDataPacket1.OnPacket := PortCom.ApdDataPacket1Packet;
//Alloco memoria per contenere il valore di ritorno della funzione da passare al software
if Prova <> '' then
Response := Prova
else
Response := 'Nessun dato';

GetMem(Result,Length(Response));
//Copio il valore di ritorno nella variabile che la funzione ritorna
Result := StrPCopy(Result, Response);
//Result := PChar(Response);
Except
//Alloco memoria per contenere il valore di ritorno della funzione da passare al software
GetMem(Result,StrLen('ERROR'));
//Copio il valore di ritorno nella variabile che la funzione ritorna
Result := StrPCopy(Result, 'ERROR');
end;
end;

Procedure Connect(Baud: PChar; COM: PChar) export; StdCall;
var Creato: String;
begin
PortCom := TPortCom.Create(nil);
try
//Configuro la porta seriale e la apro per iniziare le comunicazioni
PortCom.ApdComPort1.ComNumber := StrToInt(COM);
PortCom.ApdComPort1.Baud := StrToInt(Baud);
PortCom.ApdComPort1.Parity := pNone;
PortCom.ApdComPort1.DataBits := 8;
PortCom.ApdComPort1.StopBits := 1;
PortCom.ApdComPort1.InSize := 256;
PortCom.ApdComPort1.Open := true;
Conn := true;
except
FreeAndNil(PortCom.ApdComPort1);
end;
end;

Procedure Disconnect() export; StdCall;
begin
PortCom.ApdComPort1.open := false;
FreeAndNil(PortCom.ApdComPort1);
FreeAndNil(PortCom.ApdDataPacket1);
Conn := false;
end;

colde
23-07-2006, 21:52
UP!!

Loading