Newsgroup: it.comp.lang.delphi
Titolo: Portare un progetto da D6 a D2009 usando i package

Ho un progetto di un app piuttosto corposa fatta in Delphi 6.
Volevo riprendere in mano il codice un pï¿œ alla volta per fare del 
refactoring (che ne ha bisogno) possibilmente usando Delphi 2009 e per 
farlo pensavo di spezzare la app in tante unitï¿œ logiche che sarebbero 
diventate package di run time, mantenendo per nucleo centrale l'app in 
Delphi 6 che sarebbe diventata via via piï¿œ "magra" fino a scomparire del 
tutto.
Se non chï¿œ appena prodotto il primo package in D2009 ho scoperto che non 
ï¿œ leggibile dalle apps D6: in fase di compilazione mi restituisce "Bad 
file format: 'pippo.dcp'".
L'incompatibilitï¿œ ï¿œ completa o c'ï¿œ un barbatrucco per renderli 
compatibili? Ha a che fare con il fatto che D2009 supporta l'unicode e 
D6 no?

 D6 no?
In generale, non c'ï¿œ compatibilitï¿œ tra i file binari prodotti da diverse 
versioni dei compilatori (con l'eccezione di BDS2006 che manteneva la 
compatibilitï¿œ esplicita con la versione precedente, consentendo di 
riutilizzare i package giï¿œ acquistati).
Non capisco perï¿œ quale sia l'operazione che stai cercando di fare: 
apparentemente, vai a caricare un package D2009 in D6, e questo 
senz'altro non ï¿œ possibile.
Avendo il sorgente, puoi ricompilarlo per generare i file binari dei 
package (BPL, DCP, ...) all'interno di piï¿œ versioni differenti di 
Delphi, eventualmente aggiungendo un suffisso al package (es. 
"Pippo60.dpk" e "Pippo2009.dpk") e caricando ciascuno di questi nel 
rispettivo ambiente con la versione corretta.
Ciao,
   Marco.
-- 
MARCO BREVEGLIERI
  (
http://www.marco.breveglieri.name
)

 "Pippo60.dpk" e "Pippo2009.dpk") 
[OT]
la fantasia di noi programmatori! :D
[/OT]
come ti consiglia Marco ï¿œ ovviamente la strada migliore ma io che ci 
sono passato ti dico che devi tenere conto anche dei componenti e del 
fatto che spesso da d2009 non sono supportati. ci ho provato e non ci 
sono riuscito sto continuando a sviluppare quella app si d6
saluti

 sono riuscito sto continuando a sviluppare quella app si d6
E' proprio questo il problema.
Ho una applicazione molto grossa fatta in d6. Questa si appoggia ad una 
dll pure fatta in d6.
Ho dovuto aggiungere a questa dll dei servizi soap che sotto d6 non 
riesco a far girare e invece funzionano sotto d2009.
Inizialmente (e ingenuamente) pensavo di far diventare la dll un package 
compilato in d2009 che potesse essere  usato dalla app principale, ma 
come mi state dicendo non ï¿œ possibile.
Stranamente anche la dll compilata in d2009 non funzia se chiamata dalla 
app d6 (a meno che non abbia fatto qualche casino io :-( ).
Compilare la vecchia app d6 in d2009 neanche a parlarne, perchï¿œ proprio 
come hai detto tu usa una valanga di componenti vecchi non supportati da 
d2009.
Nel peggiore dei casi trasformerï¿œ la dll in un eseguibile con parametri 
a riga di comando, e NON DOVREBBERO ESSERCI PROBLEMI, spero.
Ma aldilï¿œ di questo problema, piï¿œ genericamente cercavo un sistema per 
fare il refactoring della vecchia app pezzo per pezzo, spezzandola in 
vari package (divide et impera).
Dovrï¿œ farlo in d6 e una volta eliminati tutti i vecchi componenti potrï¿œ 
ricompilare il tutto in d2009.

 ricompilare il tutto in d2009.
Esattamente. :)


 standard di Windows.
E' quello che ho fatto, tenendo conto che i pchar usati per passare 
stringhe nella dll compilata in d2009 diventano pwchar per la app 
chiamante in d6.
Quindi da quello che dici se non funzia ï¿œ perchï¿œ ho fatto qualche casino 
io, e non per una incompatibilitï¿œ dei compilatori.
Questo mi rincuora.

 cura o eviti di passare oggetti VCL). 
Quando dici "eviti di passare oggetti VCL" immagino che ti riferisca 
alle funzioni e procedure di interfaccia, cioï¿œ quelle che vengono esportate.
Ma nell'esecuzione di una funzione io devo fargli visualizzare una form 
che visualizzi l'avanzamento del processo.
Quindi all'interno della dll uso form come in app normali.
Si puï¿œ fare? perchï¿œ io ci sto provando, ed ottengo un comportamento 
anomalo: la form si visualizza, ma si aggiorna (cioï¿œ fa il refresh) solo 
se passo sopra con il cursore del mouse.
Ci sono momenti in cui piuttosto che fare il programmatore preferirei 
fare il fruttivendolo ;-)

Tu stai parlando di 2 diverse "operazioni" come se fossero una sola
cosa.
Una cosa è il PORTING e una è il REFACTORING.
Se le fai insieme rischi di metterti in un casino bestiale.
Io divideri le cose in due step.
Per prima cosa, il porting su d2009. DOPO penserei al refactoring.
Nota: Il passare ai runtime packages di fatto è un refactoring.
Pax vobiscum.
A.

 fare il fruttivendolo ;-)
Ti comprendo appieno! ;-)


 Per prima cosa, il porting su d2009. DOPO penserei al refactoring.
Concordo pienamente. Per quanto possano mancare componenti o possano 
esserci operazioni manuali da fare (che si stanno comunque facendo, con 
*non pochi* problemi), � la soluzione pi� appropriata se si intende fare 
uso della versione pi� aggiornata del prodotto.
Penso che evitare un porting a D2009 e alla sua VCL Unicode per passare 
poi dalla realizzazione di package alla creazione di DLL standard con 
codice compilato un po' con una versione e un po' con un altro non sia 
una soluzione meno complessa e problematica rispetto alla semplice 
migrazione a D2009, per quanto dura questa possa essere. :)


 se passo sopra con il cursore del mouse.
Per chiunque fosse interessato: Ho risolto il problema con un 
barbatrucco assurdo ma che funziona: Ho messo su ogni form un componente 
  TTimer con l'interval settato a 500 msec e l' evento ontimer con una 
riga di rem (cioï¿œ non fa niente) ma ï¿œ sufficiente a gestire il refresh 
della form.

 della form.
Onestamente, dubito che questa soluzione ti eviti grattacapi in futuro, 
anzi... :-)


 
Guarda, sono ad un livello di saturazione sufficiente per trovarla una 
*buona* soluzione.
In futuro, quando porterï¿œ tutto su d2009 e inizierï¿œ il refactoring e 
ritroverï¿œ questo accrocchio riderï¿œ molto, ma per adesso se gira va bene.
Grazie per la pazienza.

 della form.
mamma mia che cosa brutta.
A.

 mamma mia che cosa brutta.
Non sar� stilisticamente perfetto ma se funzia per il momento me lo tengo.

 Non sarà stilisticamente perfetto ma se funzia per il momento me lo tengo.
Io me ne frego dello stile... Non sono un purista..
Ma fare CONSAPEVOLMENTE una cosa come questa, ovvero, so che è sporca
ma so PER CERTO che l'alternativa richiede 30gg/u è un conto...Farla
come accrocchio senza farsi delle domande sul PERCHE' di questi strani
comportamenti è come mettere in mare delle mine e poi navigarci
dentro...Tu non sai quando, ma è probabile che una di quelle mine un
giorno la becchi, ti scoppia in faccia e ti trovi nei casini.
A.

 giorno la becchi, ti scoppia in faccia e ti trovi nei casini.
Non ho mai detto che non avrei testato il tutto, ma avendo constatato 
che il problema era *solo* il refresh delle form non mi preoccupo pi� di 
tanto.

 tanto.
..ho la sensazione di dover tornare a scuola....non so farmi capire...
Quello che voglio dire io è che, se tutto sto giro NON VA, ci potrebbe
essere qualcosa che non va molto ma molto piu grave del "solo" refresh
del form...e quel qualcosa FORSE in futuro potrebbe darti casini al
confronto dei quali un refresh del form è una passeggiata al parco....
A.

 usato il synchronize?
Hai centrato il problema. il synchronize.
Ho sempre usato il synchronize, perch� ho letto da qualche parte che 
quando un thread secondario deve aggiornare un controllo (per es. 
progress bar) sul thread principale della applicazione � bene 
sincronizzarli, ma nella dll se tolgo il synchronize tutto riprende a 
funzionare senza bisogno di accrocchi strani.
Non ho documentazione per dimostrarlo, ma probabilmente dentro la dll la 
form non riceve eventi on idle come succede dentro una applicazione 
normale che  aggiornano la form se ce ne bisogno, quandi se sincronizzo 
il thread con la form blocco entrambi finch� la form non riceve 
esternamente un messaggio per fare il refresh (tipo cursore del mouse 
che passa sopra).
Invece senza il synchronize il thread stesso aggiorna la form.
Per capirci un p� di codice:
unit MyThread;
TOnStart = procedure (const TotSteps: Integer) of object;
TOnStep = procedure (const Value: Integer) of object;
TOnStop = procedure (Sender: TObject; const Terminated: TThreadEndState) 
of object;
TMyThread = class(TThread)
protected
   FPosition: Integer;
   FTotSteps: Integer;
   FThreadState: TThreadState;
   procedure Start;
   procedure Step;
   procedure Stop;
public
   property OnStart: TOnStart read FOnStart write FOnStart;
   property OnStep: TOnStep read FOnStep write FOnStep;
   property OnStop: TOnStop read FOnStop write FOnStop;
   procedure Execute; override;
end;
implementation
procedure TMyThread.Step;
begin
   if Assigned(FOnStep) then
     FOnStep(FPosition);
end;
procedure TMyThread.Start;
begin
   if Assigned(FOnStart) then
     FOnStart(FTotSteps);
end;
procedure TMyThread.Stop;
begin
   if Assigned(FOnStop) then
     FOnStop(Self, FThreadState);
end;
procedure TMyThread.Execute;
begin
   //Conto tutti gli step coinvolti nel thread
   FTotSteps := GetSteps;
   Synchronize(Start);	
   for I := 0 to FTotSteps - 1 do
   begin
     FPosition := I;
     Synchronize(Step);
     ...	
   end;
   ...
end;
Questo sistema funzionava bene nelle applicazione vcl normali, ma nella 
dll ho dovuto usare questo approccio:
TMyThread = class(TThread)
public
   property OnStart: TOnStart read FOnStart write FOnStart;
   property OnStep: TOnStep read FOnStep write FOnStep;
   property OnStop: TOnStop read FOnStop write FOnStop;
   procedure Execute; override;
end;
implementation
procedure TMyThread.Execute;
var
   TotSteps: Integer;
begin
   //Conto tutti gli step coinvolti nel thread
   TotSteps := GetSteps;
   if Assigned(FOnStart) then
     FOnStart(TotSteps);
   for I := 0 to TotSteps - 1 do
   begin
     if Assigned(FOnSteps) then
       FOnSteps(I);	
     ...	
   end;
   ...
end;
Senza il synchronize funziona bene anche senza TTimer o altri accrocchi.

 Hai centrato il problema. il synchronize.
A proposito: grazie della dritta.

      ...        
A.

 Ancora, le chiamate sono troppe:
Questa non l'ho capita. Puoi chiarire per favore?

 Questa non l'ho capita. Puoi chiarire per favore?
Lascia stare ho capito. limitare le chiamate

 end;
Se il thread comunica al main thread soltanto l'avanzamento del compito
assegnatogli, piuttosto che usare Synchronize che viene comunque
eseguito nel thread primario bloccando il thread secondario, perch� non
provi ad usare una PostMessage ? Consegni il messaggio con
l'avanzamento. Quando il loop del main thread � pronto preleva il
messaggio aggiornando la progressbar opportunamente. Come metodo �
semplice, asincrono ed il tuo thread dovrebbe continuare a filare.
Antonio
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.9 (GNU/Linux)
Comment: Using GnuPG with Mozilla - 
http://enigmail.mozdev.org
iEYEARECAAYFAko760sACgkQYSsm1R1/E7xi1ACg1BJz/8c31sPvrxRaV6UayrVR
WF8An07g7gBYAOohlrW4bdNe5crPYeks
=10zj
-----END PGP SIGNATURE-----

 semplice, asincrono ed il tuo thread dovrebbe continuare a filare.
Gli eventi sarebbero 3, lo start con il totale degli step, lo step con 
il progresso raggiunto, e lo stop con lo stato di conclusione del thread 
(cioe concluso con successo, concluso con errore o abortito dall'utente).
E' interessante come sistema quello che proponi.
Per adesso tengo quello che usavo in precedenza, ma � utile saper fare 
la stessa cosa in pi� modi.

 la stessa cosa in pi� modi.
Puoi creare senza problemi la gestione di 3 eventi, inviando 3 messaggi
differenti gestiti dal main thread. Visto che PostMessage, oltre al tipo
di messaggio ti consente anche di inviare 2 interi, gli eventi sarebbero
ridotti a 2, ovvero ad ognuno di questi 2 messaggi invii anche il totale
degli step, anche se verr� usato solo una volta.
Se devi gestire situazione pi� complesse puoi farlo anche creando nel
mainthread una sorta di stack usando una TStringList in cui dal thread,
atomicamente usando una critical section, inserisci i tuoi messaggi
personalizzati e usi la postmessage solo per segnalare al main thread
che ci sono dei messaggi nel buffer (la stringlist); oppure con un timer
il main thread pu� controllare autonomamente l'eventuale presenza di
dati nel buffer e, sempre atomicamente, con la critical section estrarre
quanto deve.
In questo modo,  il thread compie operazioni atomiche sulla stringlist e
si "inchioda" poco, continuando a correre, mentre il mainthread fa
quello che deve a tempo debito.
Ovviamente, per l'avanzamento di una operazione io credo che la post
message sia pi� indicata e semplice da realizzare.
Antonio
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.9 (GNU/Linux)
Comment: Using GnuPG with Mozilla - 
http://enigmail.mozdev.org
iEYEARECAAYFAko/i24ACgkQYSsm1R1/E7wapACg2IyFIVAry2yuLSWGti4zef9l
V5AAoLbZQDF5rLQIz8QY/EIIlOqJ2g0O
=uA4/
-----END PGP SIGNATURE-----