Newsgroup: it.comp.lang.delphi
Titolo: Evento OnPacket ApdComPort e DLL

Ciao a tutti,
tempo fa avevo fatto un post per una richiesta di aiuto riguardante la
cattura di un evento da DLL e precisamente l'evento OnPacket del
componente ApdComPort. Un utente mi aveva fatto correggere alcune
piccole cose ma ancora non funziona, anche se l'evento si scatena non
viene catturato. Perchè?
Grazie
Il codice sorgente è questo:
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);
  ApdDataPacket1.OnPacket := PortCom.ApdDataPacket1Packet;
<--ASSEGNAZIONE EVENTO
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+chr($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;
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;

 viene catturato. Perchè?
Cosa intendi con "l'evento si scatena ma non viene catturato?" se metti
un OutputDebugString nell'handler vedi la stringa nel debugger?
Riesci a far funzionare il codice fuori da una dll?
Perche' inizializzi il pacchetto dopo aver mandato la stringa di
polling?
Alloca staticamente il buffer di ricezione secondo le dimensioni attese
della risposta (come nell'esempio dell'help, per intenderci).
Normalmente i passi per far funzionare il tutto sono:
1) crea e inizializza la comport
2) crea e inizializza il packet (disabled)
3) abilita il pacchetto
4) manda la stringa di polling
5) nell'handler dell'evento di ricezione del pacchetto gestisci il
tutto (eventualmente in asincrono postando un messaggio dopo aver
duplicato il pacchetto)
Saluti
Paolo Arosio

 Paolo Arosio
Grazie

 questo che volevi dirmi? O sono io che non ho capito una mazza?
a) non vedo traccia di una allocazione di buffer
b) vedi l'help e prova in quel modo: questo codice
procedure TPortCom.ApdDataPacket1Packet(Sender: TObject; Data: Pointer;
Size: Integer);
begin
Prova := Data;
end;
*non fa* una copia di ciò che è puntato da Data.
Aiutati: metti in una form un pulsante, un apdcomport, un
apddatapacket, un memo.
Inizializza a design time le proprietà rilevanti (lascia il pacchetto
con AutoEnable a false), compreso il gestore dell'evento OnPacket (o
OnDataPacket, non ricordo quale dei due), e possibilmente anche
dell'evento OnTimeout dello stesso datapacket
Al formShow: apri la comport
al ButtonClick: abilita il datapacket; scrivi una stringa A nel memo,
manda la stringa per la richiesta dati.
In caso di evento OnTimeout: scrivi una stringa B nel memo
In caso di evento OnDataPacket: scrivi una stringa C nel memo
Una volta fatto funzionare questo accrocchio di minima puoi vedere quel
che si riesce a combinare con l'allocazione dinamica dei componenti.
Considera comunque di tenere i componenti, anche in caso di uso via
DLL, su un DataModule; puoi sempre allocare questo dinamicamente, e ti
risparmi un po' di problemi con le varie configurazioni, oltre a
fornirti la possibilita' di mettere facilmente altri componenti (timer,
logger, etc) non visuali ma utili da avere in un unico oggettone
composto.
Saluti
Paolo Arosio

Ok, grazie al tuo aiuto sono riuscito a recuperare i dati dalla seriale
e infilarli nel buffer ma ora sorge un problema, come faccio per
recuperare i dati in formato stringa?
Ho cercato info sull'help di delphi e in google ma non ho capito ancora
come devo fare questo passaggio. Comunque grazie mille dell'aiuto!
Paolo Arosio ha scritto:


 come devo fare questo passaggio. Comunque grazie mille dell'aiuto!
Non capisco quale sia il problema: se hai una serie di caratteri in un
array di char, e questi sono solo caratteri alfanumerici non c'e'
problema. Basta appendere un null al termine dei dati validi (o meglio,
riempire sempre il buffer di null prima di recuperare i dati) e
assegnarlo a una variabile string (il viceversa con strCopy).
Se invece hai dentro dei caratteri di controllo puoi semplicemente
usare IntToHex su questi, tipo:
function BufToString(const buf: array of char);
var i: integer;
begin
   result := '';
  for i := 0 to Pred(length(buf))
    if buf[i] <= ' ' or buf[i] > 'Z' then
       result := result + '[' + IntToHex(buf[i]) + ']'
    else result := result + buf[i];
end;
Saluti
Paolo Arosio