Newsgroup: it.comp.lang.delphi
Titolo: Esportazione  classe  da  package

 Salve a tutti, ho un problema che non riesco a risolvere. In un progetto
ho una unit(form programma principale) e un package formato da una sola
unit. Volendo provare l'approccio dell'esportazione di una classe dal
package ho scritto il codice nel seguente modo:
1) Per la unit relativa al package:
   interface
   .......
   .......
   TProva = class(TPersistent)
     function ShowString: String;
   end;
   implementation
   function TProva.ShowString: String;
   begin
     Result := 'Prova';  
   end;
   initialization
     RegisterClass(TProva);
2) Per la unit relativa al programma principale:
   interface
   ......
   ......
   implementation
     procedure TForm1.Button1Click(Sender: TObject);
     var
       HandlePackage: HMODULE;
       ProvaRef: TPersistentClass; 
       Prova: TPersistent; 
     begin
       HandlePackage := LoadPackage('Package.bpl');
       if (HandlePackage > 0) then
         begin
           ProvaRef := GetClass('TProva');
           if Assigned(ProvaRef) then
             begin
               Prova := ProvaRef.Create;
               try              
                 Edit1.Text := Prova. ; // problema :-)
               finally
                 UnloadPackage(HandlePackage);
               end;
             end;
         end
       else
         ShowMessage('File  Package.bpl  not  found !!!');
     end;
Praticamente ciò che vorrei ottenere è la visualizzazione della stringa
'Prova' in una casella di testo, ma per far ciò devo accedere al metodo
ShowString della classe TProva esportata, ma non riesco ad accedervi. Come
fare quindi? Grazie a tutti in anticipo.
--- posted by geoForum on 
http://www.delphiedintorni.it

 
La prima cosa che mi viene in mente è creare una classe superiore dove 
definire le funzioni/procedure esportare nel pck, dichiararle virtual e 
  da questa far derivare la classe inserita dentro il pck con le 
funzioni/procedure implementate, nel programma linkare solo la classe 
principale con le funzioni virtual.
La seconda potrebbe essere l'uso di interfacce, ma non ricordo bene il 
funzionamento, se vai sul sito di Marco Cantu' dovrebbero esserci degli 
esempi proprio sull'uso di interfacce nei pck (se la memoria funziona 
ancora).
Goblin
-- 
Ibis et redibis non morieris in bello
http://goblinland.myminicity.com/


Veramente io possiedo il libro di Marco Cantù che spiega l'argomento delle
interfacce nei package(adatto ovviamente piu' per applicazioni
voluminose), ma nell'esempio riporta una unit generica dove è dichiarata
l'interfaccia da implementare nelle relative unit che rappresentano i vari
package dell'applicazione. Ovviamente per implementare l'interfaccia
presente nella unit generica, bisogna usare la clausola uses nelle varie
unit il che significa(correggimi se sbaglio) che la unit generica viene
compilata insieme a tutte le altre. Ma il mio obiettivo era quello di
evitare di mettere clausole uses e una volta ottenuto il class reference
della classe presente nel package tramite l'istruzione GetClass (come
appena descritto), riuscire a creare un'istanza della classe e usare i
suoi metodi :-( ..... Chissà se con i puntatori è possibile ......


 
Con le DLL è possibile usare 'GetProcAddress', ma nei pck mi sembra che 
sia sconsigliato
Goblin


Grazie per la pazienza e il tempo che mi hai dedicato, esaminerò il tuo
codice domani. Comunque smanettandoci tutta la serata sull'Help di Delphi
alla fine sono riuscito ad ottenere quello che volevo senza usare ne il
primo approccio e ne il secondo. Praticamente la soluzione è questa: nella
unit ObjAuto, c'è una funzione che si chiama GetMethodInfo che restituisce
un puntatore a un packed record contenente informazioni su un metodo di un
oggetto generico TObject. La sintassi della funzione è la seguente: 
function GetMethodInfo(Instance: TObject; const MethodName: ShortString):
PMethodInfoHeader;  dove PMethodInfoHeader = ^TMethodInfoHeader da cui
TMethodInfoHeader = packed record
  Len: Word; // lunghezza del metodo credo :-)
  Addr: Pointer; // indirizzo o puntatore 
  Name: ShortString; // nome del metodo
end;
Da qui quindi la modifica del mio event handler è la seguente:
procedure TForm1.Button1Click(Sender: TObject);
type
  // Poichè il campo del record(Addr) è un indirizzo e quindi un
  // puntatore al metodo dell'oggetto(classe) dichiaro:...... 
  TFuncShowString = function: String of object;  
var
  HandlePackage: HMODULE;
  ProvaRef: TPersistentClass; Prova: TPersistent; 
  MethodInfo: PMethodInfoHeader; // memorizzo le info della funzione 
  FuncShowString: TFuncShowString; // variabile funzione
begin
  HandlePackage := LoadPackage('Package.bpl');
  if (HandlePackage > 0) then
    begin
      ProvaRef := GetClass('TProva');
      if Assigned(ProvaRef) then
        begin
          Prova := ProvaRef.Create;
          try
            MethodInfo := GetMethodInfo(Prova, 'ShowString');
            // calcolo l'indirizzo del metodo puntando ad esso....
            @FunShowString := MethodInfo.Addr;
            // visualizzo il risultato della funzione sulla casella
            // di testo cioè la stringa 'Prova'
            Edit1.Text := ' ' + FunShowString;
          finally
            FreeAndNil(Prova); UnloadPackage(HandlePackage);
          end;
        end;
    end
  else
    ShowMessage('File  Package.bpl  not  found !!!');
end;
Come lo vedi questo approccio? Non è piu' sbrigativo? Da principiante però
mi chiedo se puo' essere professionale.....che ne pensi?


 
Mi considero un buon hobbista non mi sento in grado di giudicare lascio 
questo incarico a chi ci capisce un po' piu' di me :)
Cmq lo vedo molto simile al mio, in fondo "il prototipo" della funzione 
da usare da qualche parte la devi dichiarare, io uso una classe base, tu 
un puntatore ... non so dirti quale sia "il migliore".



Beh, di sicuro neanche io posso permettermi di giudicare i vari approcci,
anche se penso che in generale(posso sbagliarmi visto che sono un
principiante) che l'uso dei puntatori sia un'ottima alternativa anche per
la gestione dinamica della memoria e la sua ottimizzazione, ma d'altronde
come si dice....tutte le strade portano a Roma :-) (anche se questo detto
non penso sia valido per progetti complessi dove bisogna sicuramente
decidere l'approccio migliore da usare). Bisognerebbe chiedere a qualche
guru :-)......Comunque grazie di nuovo ciao alla prossima.
