Italian community of Lazarus and Free Pascal

Programmazione => Generale => Topic aperto da: Simon75 - Dicembre 19, 2012, 09:11:17 am

Titolo: DLL con SaveDialog
Inserito da: Simon75 - Dicembre 19, 2012, 09:11:17 am
Ciao a tutti, attulamente sto utilizzando un software di automatismi, e mi è nata l'esigenza di realizzare una Dll con SaveDialog ma non so come applicarla qualcuno può aiutarmi.
Allego una dll che ho creato come esempio per fare la somma, moltiplicazione.
Codice: [Seleziona]
library Somma;

uses
  SysUtils, Windows, Classes;



// -------------------------------------------------------------------------------

Const  Inputs = 2;  // quantita entrata
       Outputs = 2; // quantita uscita

       {INPUTS}  // nome per numero di entrata
        I0 = 0;  // valore I0 = PInput[I0] ossia PInput[0]
        I1 = 1;  // valore I1 = PInput[I1] ossia PInput[1]
     // I2 = 2;
     // I3 = 3;
// ... I99 = 99;

       {OUTPUTS} // nome per numero di uscita
        Q0 = 0;  // valore Q0 = POutput[Q0] ossia POutput[0]
        Q1 = 1;  // valore Q1 = POutput[Q1] ossia POutput[1]
     // Q2 = 2;
     // Q3 = 3;
// ... Q99 = 99;

       {USER}   // nome per numero di variabile, I valori vengono memorizzati
        U0 = 0; // valore U0 = PUser[U0] ossia PUser[0]
     // U1 = 1;
     // U2 = 2;
     // U3 = 3;
// ... U99 = 99;

// I0,I1,I2,I3,Q0,Q1,Q2,Q3,U0,U1,U2,U3
// I nomi possono essere qualsiasi, sono case-insensitive

Type TDLLParams = array[0..100] of extended; // ProfiLab DLL parametro Type
     PDLLParams = ^TDLLParams;               // ProfiLab DLL parametro Pointer

// -------------------------------------------------------------------------------

function NumInputs: Byte;
begin
  result := Inputs; // trasferire quantita entrata
end;

// -------------------------------------------------------------------------------

function NumOutputs: Byte;
begin
  result := Outputs; // trasferire quantita uscita
end;

// -------------------------------------------------------------------------------

function InputName(Channel: Byte): ShortString; // trasferire nome di entrata
begin
  case Channel of
   I0 : result := 'I0'; // nome di pin I0
   I1 : result := 'I1'; // nome di pin I1
  end;
end;

// -------------------------------------------------------------------------------

Function OutputName(Channel: Byte): ShortString; // trasferire nome di uscita
begin
  case Channel of
   Q0 : result := 'Q0'; // nome di pin Q0
   Q1 : result := 'Q1'; // nome di pin Q1
  end;
end;

// -------------------------------------------------------------------------------

Procedure SimStart(PInput,POutput,PUser: PDLLParams); // Routine viene eseguita solo al primo avvio
begin
 // solo per inizializzare
end;

// -------------------------------------------------------------------------------

Procedure Calculate(PInput,POutput,PUser: PDLLParams); // Routine e permanente
begin

  // Calcola somma di due numeri
  POutput^[Q0] := PInput^[I0] + PInput^[I1];

  // Prodotto di due numeri per il calcolo
  POutput^[Q1] := PInput^[I0] * PInput^[I1];

  // Differenza tra due valori
  PUser^[U0] := PInput^[I0] - PInput^[I1];

  // piu funzioni

end;

// -------------------------------------------------------------------------------

Procedure SimStop(PInput,POutput,PUser: PDLLParams); // Routine viene eseguita solo in fase di chiusura
begin
  // solo in chiusura
end;

// -------------------------------------------------------------------------------

//export methods for ProfiLab
exports SimStart,
        SimStop,
        NumInputs,
        NumOutputs,
        Calculate,
        InputName,
        OutputName;

begin
end.
Vorrei sapere come posso inserire una SaveDialog in una DLL con queste caratteristiche?
Ecco il risultato della DLL sopra citata:
(http://i46.tinypic.com/311t1zc.png)
Titolo: Re:DLL con SaveDialog
Inserito da: nomorelogic - Dicembre 19, 2012, 06:05:19 pm
devi istanziare l'oggetto all'interno della funzione, ad esempio:

Codice: [Seleziona]
function SaveToFile: string;
var d: TSaveDialog;
begin
   result := '';
   d := TSaveDialog.Create(self); // vado a memoria non ricordo i parametri di create...
   try
     if d.Execute then
     begin
         result := d.FileName;
     end;
   finally
     d.Free;
   end
end;


quando la richiami, se l'utente clicca su [OK], ti ritorna la fullpath dove salvare il tu file
Titolo: Re:DLL con SaveDialog
Inserito da: Simon75 - Dicembre 19, 2012, 11:16:54 pm
Ciao nomorelogic, grazie per avermi risposto potresti indicarmi dove inserire nella mia dll quella funzione?
Naturalmente cancellando quello che non serve poichè è una dll somma e altro.
Sono vincolato a seguire delle regole per fare il componente dll ti allego le regole che mi chiede il software:

DLL-Import
 
Included in version:
DMM-ProfiLab:      No
Digital-ProfiLab:      No
ProfiLab-Expert:      Yes
 
This component offers a programming interface, which makes it possible to create your own ProfiLab components, for example to control self-made hardware devices, etc.
For that purpose you need a programming language, that allows you to compile DLL-files
(Dynamic Link Libraries), and you need some programming experience, as well.
Programming your own component, you have to meet some requirements of ProfiLab.
For example your DLL must export certain functions, that define the numbers of component inputs and outputs, the pin names and the internal function of the component.
 
The following function are necessary for a component. The modified C++ versions use DOUBLE instead of EXTENDED and PCHAR instead of STRING.
 
Delphi: function NumInputs: Byte;
C++: unsigned char _stdcall NumInputs()
alternative:
Delphi: function NumInputsEx(PUser: PDLLParams): Byte;
C++: unsigned char _stdcall CNumInputsEx(double *PUser)
The result of this function must return a byte value that defines the number of inputs of your component. The extended function type NumInputsEx is useful, if the number of inputs depends on configuration data stored in PUser.
 
Delphi: function NumOutputs: Byte;
C++: unsigned char _stdcall NumOutputs()
alternative:
Delphi: function NumOutputsEx(PUser: PDLLParams): Byte;
C++: unsigned char _stdcall CNumOutputsEx(double *PUser)
The result of this function must return a byte value that defines the number of outputs of your component. The extended function type NumOutputsEx is useful, if the number of outputs depends on configuration data stored in PUser.
 
Delphi: function InputName(Channel: Byte): ShortString;
void _stdcall GetInputName(unsigned char Channel, unsigned char *Name)
The result of this function must deliver a short text for the pin description for each input pin (channel) of your component. ProfiLab calls this function for each input pin, to request the corresponding description. The parameter CHANNELS identifies the pin and runs from 0 to NumInputs-1.
 
Delphi: function OutputName(Channel: Byte): ShortString;
C++: void _stdcall GetOutputName(unsigned char Channel, unsigned char *Name)
The result of this function must deliver a short text for the pin description for each output pin (channel) of your component. ProfiLab calls this function for each output pin, to request the corresponding description. The parameter CHANNELS identifies the pin and runs from 0 to NumOutputs-1.
 
Delphi: Procedure Calculate(PInput,POutput,PUser: PDLLParams);
C++: void _stdcall CCalculate(double *PInput, double *POutput, double *PUser)
This is the main calculation procedure of your component, which defines how your component works. The procedure parameters PINPUT, POUTPUT and PUSER offer three pointer variables with the following function:
 
The pointer PINPUT points to a memory area, in which input values are stored, so that the DLL can access the input values of the component.
The pointer POUTPUT points to a memory area, in which output values are stored, so that the DLL can set the output values of the component.
The pointer PUSER points to a memory area, where the DLL can store its own (local) values. Background: Variables defined in the DLL are global variables. Values stored to global variables will overwrite each other, if a DLL component is used more than once in a ProfiLab project. To have local variables available, ProfiLab hands out the pointer PUSER to the DLL, so that the DLL can store local data in the memory area that PUSER points to.
 
If you don´t want to use PUSER, but you need to declare variables in the DLL that are meant to be local (for components that are used more than once in a ProfiLab project), you can rename the DLL file and import it in ProfiLab with different filenames, as well.
 
Each of the three pointers PINPUT, POUTPUT and PUSER points to an array of 100 EXTENDED variables. All three pointer are declared as type PDLLParams. The declaration in Delphis is as follows:
 
type TDLLParams = array[0..100] of extended;
     PDLLParams = ^TDLLParams;
 
C++ function types hand out this kind of memory pointer as (double *PInput) parameter for example.
 
The array of PINPUT offers the input values of the component. The input values can be accessed as follows:
 
PInput^[0] contains the numeric value of the first input,
PInput^[1] contains the numeric value of the second input, and so on...
 
The array of POUTPUT offers the output values of the component. The output values can be set as follows:
 
POutput^[0] must be set with the numeric value for the first output,
POutput^[1] must be set with the numeric value for the second output, and so on...
 
PUser^[0] to PUser^[99] can be used to store numeric user values. The values of these variables are saved in the ProfiLab project file, so that values are available agein, when the project is loaded next time. The variable PUser^[100] is set by ProfiLab and contains the number of the DLL component: 1 fo DLL1, 2 for DLL2, and so on.
 
The procedure CALCULATE is called repeatedly while ProfiLab is in RUN mode, to hand out new input values to the DLL and to request new output values from the DLL. This means that this procedure must be programmed as short as possible, and must not contain any pauses (WAIT loops or SLEEP commands) that waste time. After reading input values and setting new output vaues this routine should be terminated as soon as possible. The time spent in this procedure will directly influence the simulation frequency of ProfiLab.
 
Delphi: Procedure CalculateEx(PInput,POutput,PUser: PDLLParams; PStrings: PStringParams);
C++: void _stdcall CCalculateEx(double *PInput, double *POutput, double *PUser; StringParam PStrings)
This method was introduced to allow string processing with DLL´s. It may be used as alternative for CALCULATE. Parameter PSTRINGS were added for interfacing string data. Its Delphi delclaration is as follows:
 
type TStringParams = array[0..100] of PChar;
     PStringParams = ^TStringParams;
 
Each input/output (max. 100) has a null-terminated character pointer (PChar) assigned, which points to a memory space that is provided by ProfiLab. Right before ProfiLab enters the method, data is fetched from the $inputs. After leaving the method data is handed out through the $outputs. It is not distinguished between inputs and outputs. This means that Input 0 and Output 0 for example share the same PChar. To make a pin become a string input or string output its pin name must be declared with a leading '$' character. Examples for string processing with DLL´s and ProfiLab are available.
 
Delphi: Procedure SimStart(PInput,POutput,PUser: PDLLParams);
C++: void _stdcall CSimStart(double *PInput, double *POutput, double *PUser)
This procedure is called once, when the ProfiLab project enters the RUN mode, and can be used to initialize DLL variables, etc. The parameters have been explained before.
 
Delphi: Procedure SimStop(PInput,POutput,PUser: PDLLParams);
C++: void _stdcall CSimStop(double *PInput, double *POutput, double *PUser)
This procedure is called once, when RUN mode is terminated, and can be used to close open files, etc. The parameters have been explained before.
 
Delphi: Procedure Configure(UserValues: PDLLParam);
C++: void _stdcall CConfigure(double *PUser)
As soon as your DLL exports this procedure, the button CONFIGURE... in the property dialogue of the component is enabled. With a click on this button, ProfiLab will jump to your CONFIGURE procedure, where you can add your own setup dialogue for your DLL.
 
These very few routines make it possible to program any ProfiLab component you have in mind. For example you could program hardware components that control special hardware devices, or create components that execute complex calculations.
If you want to program a component with digital outputs, simply set the numeric output vaules to 5 for HIGH levels, or to 0 for LOW levels. Numeric inputs higher than 2.5 should be interpreted as HIGH levels, numeric inputs lower then 2,5 as LOW leves.
 
Your compiled DLL file can be loaded in the property dialogue of the component. All imported functions and procedures are listed in the dialogue. The component will then appear in the circuit as it is defined in the DLL. To be conform with C-Compiler conventions, names of functions and procedure may begin with an underline character _ as well. For example _SimStart instead of SimStart.
 
Compiling your own DLL project make sure that the linker option "Dynamic RTL" is disabled. Otherwise the DLL can not be loaded on systems without installed C++ environment.
Titolo: Re:DLL con SaveDialog
Inserito da: nomorelogic - Dicembre 20, 2012, 10:13:57 am
ciao Simon
ho notato che nella tua dll non c'è né la sezione "interface", né la "implementation".

In generale nella sezione interface andrebbero tutte le intestazioni delle funzioni e procedure che poi la dll esporta tramite export.

In implementation ci vanno, appunto, le implementazioni delle funzioni e procedure dichiarate prima in interface.

Credo che dovresti implementarle nella tua dll.
Per il dove mettere la funzione, dipende dal fatto se la vuoi rendere pubblica (e cioè la dichiari anche in export) o no. Se è una funzione "privata" va solo sotto implementation.

Spero di esserti stato utile.
ciao
Titolo: Re:DLL con SaveDialog
Inserito da: Simon75 - Dicembre 20, 2012, 02:23:51 pm
Ciao, ho provato così, ma genera questo errore:

project1.pas(95,20) Hint: Parameter "PInput" not used
project1.pas(95,27) Hint: Parameter "POutput" not used
project1.pas(95,35) Hint: Parameter "PUser" not used
project1.pas(109,20) Error: Wrong number of parameters specified for call to "ApriOpenDialog"project1.pas(50,11) Hint: Found declaration: ApriOpenDialog(TForm);
project1.pas(142) Fatal: There were 1 errors compiling module, stopping

Allego il sorgente con relativa modifica:

Codice: [Seleziona]
library Project1;

{$mode objfpc}{$H+}

uses
   Interfaces, Classes, SysUtils, Windows, FileUtil, Forms, Controls,
Graphics, Dialogs;
   { you can add units after this }


// questa direttiva l'ho tolta perchè non mi creava la dll, mi sono documentato sul forum lazarus {$R *.RES}




Const  Inputs = 2;  // quantita entrata
        Outputs = 2; // quantita uscita

        {INPUTS}  // nome per numero di entrata
         I0 = 0;  // valore I0 = PInput[I0] ossia PInput[0]
         I1 = 1;  // valore I1 = PInput[I1] ossia PInput[1]
      // I2 = 2;
      // I3 = 3;
// ... I99 = 99;

        {OUTPUTS} // nome per numero di uscita
         Q0 = 0;  // valore Q0 = POutput[Q0] ossia POutput[0]
         Q1 = 1;  // valore Q1 = POutput[Q1] ossia POutput[1]
      // Q2 = 2;
      // Q3 = 3;
// ... Q99 = 99;

        {USER}   // nome per numero di variabile, I valori vengono memorizzati

         U0 = 0; // valore U0 = PUser[U0] ossia PUser[0]
      // U1 = 1;
      // U2 = 2;
      // U3 = 3;
// ... U99 = 99;

// I0,I1,I2,I3,Q0,Q1,Q2,Q3,U0,U1,U2,U3
// I nomi possono essere qualsiasi, sono case-insensitive

Type TDLLParams = array[0..100] of extended; // ProfiLab DLL parametro Type
      PDLLParams = ^TDLLParams;               // ProfiLab DLL parametro Pointer




Procedure ApriOpenDialog(finestra: TForm);
var pannello: TOpenDialog;
begin
   pannello :=  TOpenDialog.Create(finestra);
   pannello.Execute();
end;


function NumInputs: Byte;
begin
   result := Inputs; // trasferire quantita entrata
end;



function NumOutputs: Byte;
begin
   result := Outputs; // trasferire quantita uscita
end;




function InputName(Channel: Byte): ShortString; // trasferire nome di entrata

begin
   case Channel of
    I0 : result := 'I0'; // nome di pin I0
    I1 : result := 'I1'; // nome di pin I1
   end;
end;




Function OutputName(Channel: Byte): ShortString; // trasferire nome di uscita

begin
   case Channel of
    Q0 : result := 'Q0'; // nome di pin Q0
    Q1 : result := 'Q1'; // nome di pin Q1
   end;
end;


Procedure SimStart(PInput,POutput,PUser: PDLLParams); // Routine viene eseguita solo al primo avvio

begin
  // solo per inizializzare
end;




Procedure Calculate(PInput,POutput,PUser: PDLLParams); // Routine è permanente

begin

   // Apri la finestra di dialogo TOpendialog
    POutput^[Q0] :=ApriOpenDialog ;

   // Prodotto di due numeri per il calcolo
   POutput^[Q1] := PInput^[I0] * PInput^[I1];

   // Differenza tra due valori
   PUser^[U0] := PInput^[I0] - PInput^[I1];

   // piu funzioni

end;


Procedure SimStop(PInput,POutput,PUser: PDLLParams); // Routine viene eseguita solo in fase di chiusura

begin
   // solo in chiusura
end;


//export methods for ProfiLab
exports SimStart,
         SimStop,
         NumInputs,
         NumOutputs,
         Calculate,
         InputName,
         OutputName,
         ApriOpenDialog;

begin
end. 

Titolo: Re:DLL con SaveDialog
Inserito da: nomorelogic - Dicembre 20, 2012, 02:52:53 pm
se dichiari
Procedure ApriOpenDialog(finestra: TForm);
non ci sono valori di ritorno e quindi nella chiamata
 POutput^[Q0] :=ApriOpenDialog ;
ci sono 2 errori:

prova dichiararla così:

Codice: [Seleziona]
function ApriOpenDialog: ShortString;
var pannello: TOpenDialog;
begin
   pannello :=  TOpenDialog.Create(nil);
   if pannello.Execute then
      result := pannello.FileName
   else
      result := '';
end;

poi quando è ora di chiamarla:
Codice: [Seleziona]
Procedure Calculate(PInput,POutput,PUser: PDLLParams); // Routine è permanente
var s: ShortString;
begin

   // Apri la finestra di dialogo TOpendialog
    s :=ApriOpenDialog ;

   // poi valorizzi
    POutput^[Q0] :=  ...

end;
Titolo: Re:DLL con SaveDialog
Inserito da: Simon75 - Dicembre 20, 2012, 03:44:27 pm
Ciao nomorelogic,
Ecco il sorgente ma ho ancora questo errore:
Codice: [Seleziona]
project1.pas(99,20) Hint: Parameter "PInput" not used
project1.pas(99,27) Hint: Parameter "POutput" not used
project1.pas(99,35) Hint: Parameter "PUser" not used
project1.pas(109,4) Error: Illegal expression
project1.pas(109,8) Fatal: Syntax error, ";" expected but "identifier S" found



Codice: [Seleziona]
library Project1;

{$mode objfpc}{$H+}

uses
   Interfaces, Classes, SysUtils, Windows, FileUtil, Forms, Controls,
Graphics, Dialogs;
   { you can add units after this }


// questa direttiva l'ho tolta perchè non mi creava la dll, mi sono documentato sul forum lazarus {$R *.RES}




Const  Inputs = 2;  // quantita entrata
        Outputs = 2; // quantita uscita

        {INPUTS}  // nome per numero di entrata
         I0 = 0;  // valore I0 = PInput[I0] ossia PInput[0]
         I1 = 1;  // valore I1 = PInput[I1] ossia PInput[1]
      // I2 = 2;
      // I3 = 3;
// ... I99 = 99;

        {OUTPUTS} // nome per numero di uscita
         Q0 = 0;  // valore Q0 = POutput[Q0] ossia POutput[0]
         Q1 = 1;  // valore Q1 = POutput[Q1] ossia POutput[1]
      // Q2 = 2;
      // Q3 = 3;
// ... Q99 = 99;

        {USER}   // nome per numero di variabile, I valori vengono memorizzati

         U0 = 0; // valore U0 = PUser[U0] ossia PUser[0]
      // U1 = 1;
      // U2 = 2;
      // U3 = 3;
// ... U99 = 99;

// I0,I1,I2,I3,Q0,Q1,Q2,Q3,U0,U1,U2,U3
// I nomi possono essere qualsiasi, sono case-insensitive

Type TDLLParams = array[0..100] of extended; // ProfiLab DLL parametro Type
      PDLLParams = ^TDLLParams;               // ProfiLab DLL parametro Pointer




function ApriOpenDialog: ShortString;
var pannello: TOpenDialog;
begin
   pannello :=  TOpenDialog.Create(nil);
   if pannello.Execute then
      result := pannello.FileName
   else
      result := '';
end;



function NumInputs: Byte;
begin
   result := Inputs; // trasferire quantita entrata
end;



function NumOutputs: Byte;
begin
   result := Outputs; // trasferire quantita uscita
end;




function InputName(Channel: Byte): ShortString; // trasferire nome di entrata

begin
   case Channel of
    I0 : result := 'I0'; // nome di pin I0
    I1 : result := 'I1'; // nome di pin I1
   end;
end;




Function OutputName(Channel: Byte): ShortString; // trasferire nome di uscita

begin
   case Channel of
    Q0 : result := 'Q0'; // nome di pin Q0
    Q1 : result := 'Q1'; // nome di pin Q1
   end;
end;


Procedure SimStart(PInput,POutput,PUser: PDLLParams); // Routine viene eseguita solo al primo avvio

begin
  // solo per inizializzare
end;


Procedure Calculate(PInput,POutput,PUser: PDLLParams); // Routine è permanente

begin
   var s: ShortString;
   begin

      // Apri la finestra di dialogo TOpendialog
       s :=ApriOpenDialog ;

      // poi valorizzi
       POutput^[Q0] :=ApriOpenDialog ;

   // piu funzioni

end;


Procedure SimStop(PInput,POutput,PUser: PDLLParams); // Routine viene eseguita solo in fase di chiusura

begin
   // solo in chiusura
end;


//export methods for ProfiLab
exports SimStart,
         SimStop,
         NumInputs,
         NumOutputs,
         Calculate,
         InputName,
         OutputName,
         ApriOpenDialog;

begin
end.
         

Titolo: Re:DLL con SaveDialog
Inserito da: Stilgar - Dicembre 20, 2012, 04:09:53 pm
Codice: [Seleziona]
 
begin
   var s: ShortString;
   begin
Il copia e incolla va bene, ma togli le cose che non centrano ... hai 2 begin e in mezzo un var ...

Altra considerazione ...
Codice: [Seleziona]
        POutput^[Q0] :=ApriOpenDialog ;
Ma come hai dichiarato questo parametro?
Codice: [Seleziona]
Procedure Calculate(PInput,POutput,PUser: PDLLParams); // Routine è permanente 
Credo che il compilatore possa anche farela passare liscia (se si incasina con i puntatori o imposti che non deve fare il controllo di tipo sui puntatori stessi). Ma credo che poi non ti vadano a buon fine le chiamate.
PDLLParams non è dichiarato come array di numeri in virgola mobile?
Tu assegni una stringa ... (Short per giunta).
Fammi sapere ...
Stilgar
Titolo: Re:DLL con SaveDialog
Inserito da: Simon75 - Dicembre 20, 2012, 04:18:57 pm
Si che stupido grazie :)
ma non ci sono ancora:

project1.pas(116,23) Error: Incompatible types: got "ShortString" expected "Extended"

Codice: [Seleziona]

Procedure Calculate(PInput,POutput,PUser: PDLLParams); // Routine è permanente

   var s: ShortString;

   begin

      // Apri la finestra di dialogo TOpendialog
       s :=ApriOpenDialog;

      // poi valorizzi
       POutput^[Q0] :=ApriOpenDialog ;

   // piu funzioni

end;               


Mi da l'errore qui :
Codice: [Seleziona]
// poi valorizzi
       POutput^[Q0] :=ApriOpenDialog ; 
Titolo: Re:DLL con SaveDialog
Inserito da: Stilgar - Dicembre 20, 2012, 04:21:28 pm
Ok, il compilatore non si è incasinato.
Stai carcando di assegnare una stringa (short string) ad un puntatore di numero in virgola mobile.
Non sono modelli compatibili in memoria.
Puoi impostare che i parametri sono puntatori generici,ma non so se il simulatore sia in grado di gestirlo ... non lo conosco, quindi mi posso permettere di fare solo congetture.

Stilgar
Titolo: Re:DLL con SaveDialog
Inserito da: Simon75 - Dicembre 20, 2012, 05:23:46 pm
Simulatore dici il programma di automatismi che uso?
Come faccio a dichiararli generici i puntatori?
riferito a questo?
Codice: [Seleziona]

Type TDLLParams = array[0..100] of extended; // ProfiLab DLL parametro Type
      PDLLParams = ^TDLLParams;               // ProfiLab DLL parametro Pointer


Titolo: Re:DLL con SaveDialog
Inserito da: Stilgar - Dicembre 20, 2012, 10:36:46 pm
Codice: [Seleziona]

Type TDLLParams = array[0..100] of extended; // ProfiLab DLL parametro Type
      PDLLParams = ^TDLLParams;               // ProfiLab DLL parametro Pointer

Codice: [Seleziona]

Type TDLLParams = array[0..100] of Pointer; // ProfiLab DLL parametro Type
      PDLLParams = ^TDLLParams ;               // ProfiLab DLL parametro Pointer

Sì il programma che deve caricare questa DLL.

Stilgar



Titolo: Re:DLL con SaveDialog
Inserito da: Simon75 - Dicembre 21, 2012, 09:11:48 am
Ciao nomorelogic, grazie per avermi risposto potresti indicarmi dove inserire nella mia dll quella funzione?
Naturalmente cancellando quello che non serve poichè è una dll somma e altro.
Sono vincolato a seguire delle regole per fare il componente dll ti allego le regole che mi chiede il software:

DLL-Import
 
Included in version:
DMM-ProfiLab:      No
Digital-ProfiLab:      No
ProfiLab-Expert:      Yes
 
This component offers a programming interface, which makes it possible to create your own ProfiLab components, for example to control self-made hardware devices, etc.
For that purpose you need a programming language, that allows you to compile DLL-files
(Dynamic Link Libraries), and you need some programming experience, as well.
Programming your own component, you have to meet some requirements of ProfiLab.
For example your DLL must export certain functions, that define the numbers of component inputs and outputs, the pin names and the internal function of the component.
 
The following function are necessary for a component. The modified C++ versions use DOUBLE instead of EXTENDED and PCHAR instead of STRING.
 
Delphi: function NumInputs: Byte;
C++: unsigned char _stdcall NumInputs()
alternative:
Delphi: function NumInputsEx(PUser: PDLLParams): Byte;
C++: unsigned char _stdcall CNumInputsEx(double *PUser)
The result of this function must return a byte value that defines the number of inputs of your component. The extended function type NumInputsEx is useful, if the number of inputs depends on configuration data stored in PUser.
 
Delphi: function NumOutputs: Byte;
C++: unsigned char _stdcall NumOutputs()
alternative:
Delphi: function NumOutputsEx(PUser: PDLLParams): Byte;
C++: unsigned char _stdcall CNumOutputsEx(double *PUser)
The result of this function must return a byte value that defines the number of outputs of your component. The extended function type NumOutputsEx is useful, if the number of outputs depends on configuration data stored in PUser.
 
Delphi: function InputName(Channel: Byte): ShortString;
void _stdcall GetInputName(unsigned char Channel, unsigned char *Name)
The result of this function must deliver a short text for the pin description for each input pin (channel) of your component. ProfiLab calls this function for each input pin, to request the corresponding description. The parameter CHANNELS identifies the pin and runs from 0 to NumInputs-1.
 
Delphi: function OutputName(Channel: Byte): ShortString;
C++: void _stdcall GetOutputName(unsigned char Channel, unsigned char *Name)
The result of this function must deliver a short text for the pin description for each output pin (channel) of your component. ProfiLab calls this function for each output pin, to request the corresponding description. The parameter CHANNELS identifies the pin and runs from 0 to NumOutputs-1.
 
Delphi: Procedure Calculate(PInput,POutput,PUser: PDLLParams);
C++: void _stdcall CCalculate(double *PInput, double *POutput, double *PUser)
This is the main calculation procedure of your component, which defines how your component works. The procedure parameters PINPUT, POUTPUT and PUSER offer three pointer variables with the following function:
 
The pointer PINPUT points to a memory area, in which input values are stored, so that the DLL can access the input values of the component.
The pointer POUTPUT points to a memory area, in which output values are stored, so that the DLL can set the output values of the component.
The pointer PUSER points to a memory area, where the DLL can store its own (local) values. Background: Variables defined in the DLL are global variables. Values stored to global variables will overwrite each other, if a DLL component is used more than once in a ProfiLab project. To have local variables available, ProfiLab hands out the pointer PUSER to the DLL, so that the DLL can store local data in the memory area that PUSER points to.
 
If you don´t want to use PUSER, but you need to declare variables in the DLL that are meant to be local (for components that are used more than once in a ProfiLab project), you can rename the DLL file and import it in ProfiLab with different filenames, as well.
 
Each of the three pointers PINPUT, POUTPUT and PUSER points to an array of 100 EXTENDED variables. All three pointer are declared as type PDLLParams. The declaration in Delphis is as follows:
 
type TDLLParams = array[0..100] of extended;
     PDLLParams = ^TDLLParams;
 
C++ function types hand out this kind of memory pointer as (double *PInput) parameter for example.
 
The array of PINPUT offers the input values of the component. The input values can be accessed as follows:
 
PInput^[0] contains the numeric value of the first input,
PInput^[1] contains the numeric value of the second input, and so on...
 
The array of POUTPUT offers the output values of the component. The output values can be set as follows:
 
POutput^[0] must be set with the numeric value for the first output,
POutput^[1] must be set with the numeric value for the second output, and so on...
 
PUser^[0] to PUser^[99] can be used to store numeric user values. The values of these variables are saved in the ProfiLab project file, so that values are available agein, when the project is loaded next time. The variable PUser^[100] is set by ProfiLab and contains the number of the DLL component: 1 fo DLL1, 2 for DLL2, and so on.
 
The procedure CALCULATE is called repeatedly while ProfiLab is in RUN mode, to hand out new input values to the DLL and to request new output values from the DLL. This means that this procedure must be programmed as short as possible, and must not contain any pauses (WAIT loops or SLEEP commands) that waste time. After reading input values and setting new output vaues this routine should be terminated as soon as possible. The time spent in this procedure will directly influence the simulation frequency of ProfiLab.
 
Delphi: Procedure CalculateEx(PInput,POutput,PUser: PDLLParams; PStrings: PStringParams);
C++: void _stdcall CCalculateEx(double *PInput, double *POutput, double *PUser; StringParam PStrings)
This method was introduced to allow string processing with DLL´s. It may be used as alternative for CALCULATE. Parameter PSTRINGS were added for interfacing string data. Its Delphi delclaration is as follows:
 
type TStringParams = array[0..100] of PChar;
     PStringParams = ^TStringParams;
 
Each input/output (max. 100) has a null-terminated character pointer (PChar) assigned, which points to a memory space that is provided by ProfiLab. Right before ProfiLab enters the method, data is fetched from the $inputs. After leaving the method data is handed out through the $outputs. It is not distinguished between inputs and outputs. This means that Input 0 and Output 0 for example share the same PChar. To make a pin become a string input or string output its pin name must be declared with a leading '$' character. Examples for string processing with DLL´s and ProfiLab are available.
 
Delphi: Procedure SimStart(PInput,POutput,PUser: PDLLParams);
C++: void _stdcall CSimStart(double *PInput, double *POutput, double *PUser)
This procedure is called once, when the ProfiLab project enters the RUN mode, and can be used to initialize DLL variables, etc. The parameters have been explained before.
 
Delphi: Procedure SimStop(PInput,POutput,PUser: PDLLParams);
C++: void _stdcall CSimStop(double *PInput, double *POutput, double *PUser)
This procedure is called once, when RUN mode is terminated, and can be used to close open files, etc. The parameters have been explained before.
 
Delphi: Procedure Configure(UserValues: PDLLParam);
C++: void _stdcall CConfigure(double *PUser)
As soon as your DLL exports this procedure, the button CONFIGURE... in the property dialogue of the component is enabled. With a click on this button, ProfiLab will jump to your CONFIGURE procedure, where you can add your own setup dialogue for your DLL.
 
These very few routines make it possible to program any ProfiLab component you have in mind. For example you could program hardware components that control special hardware devices, or create components that execute complex calculations.
If you want to program a component with digital outputs, simply set the numeric output vaules to 5 for HIGH levels, or to 0 for LOW levels. Numeric inputs higher than 2.5 should be interpreted as HIGH levels, numeric inputs lower then 2,5 as LOW leves.
 
Your compiled DLL file can be loaded in the property dialogue of the component. All imported functions and procedures are listed in the dialogue. The component will then appear in the circuit as it is defined in the DLL. To be conform with C-Compiler conventions, names of functions and procedure may begin with an underline character _ as well. For example _SimStart instead of SimStart.
 
Compiling your own DLL project make sure that the linker option "Dynamic RTL" is disabled. Otherwise the DLL can not be loaded on systems without installed C++ environment.

Il perchè ho scritto tali parametri è scritto qui poichè non posso far diversamente.

Vorrei inizialmente far aprire una OpenDialog premendo un pulsante che ho già in libreria allego l'esempio:

(http://i50.tinypic.com/2s5z1i8.jpg)

Ho modificato il codice inserendo nell'ingresso I0 l'apertura dell'OpenDialog ma ho sempre problemi con i puntatori come posso fare? Grazie :)

Codice: [Seleziona]

library Project1;

{$mode objfpc}{$H+}

uses
   Interfaces, Classes, SysUtils, Windows, FileUtil, Forms, Controls,
Graphics, Dialogs;
   { you can add units after this }


// questa direttiva l'ho tolta perchè non mi creava la dll, mi sono documentato sul forum lazarus {$R *.RES}




Const  Inputs = 2;  // quantita entrata
        Outputs = 2; // quantita uscita

        {INPUTS}  // nome per numero di entrata
         I0 = 0;  // valore I0 = PInput[I0] ossia PInput[0]
         I1 = 1;  // valore I1 = PInput[I1] ossia PInput[1]
      // I2 = 2;
      // I3 = 3;
// ... I99 = 99;

        {OUTPUTS} // nome per numero di uscita
         Q0 = 0;  // valore Q0 = POutput[Q0] ossia POutput[0]
         Q1 = 1;  // valore Q1 = POutput[Q1] ossia POutput[1]
      // Q2 = 2;
      // Q3 = 3;
// ... Q99 = 99;

        {USER}   // nome per numero di variabile, I valori vengono memorizzati

         U0 = 0; // valore U0 = PUser[U0] ossia PUser[0]
      // U1 = 1;
      // U2 = 2;
      // U3 = 3;
// ... U99 = 99;

// I0,I1,I2,I3,Q0,Q1,Q2,Q3,U0,U1,U2,U3
// I nomi possono essere qualsiasi, sono case-insensitive

Type TDLLParams = array[0..100] of extended; // ProfiLab DLL parametro Type
      PDLLParams = ^TDLLParams;               // ProfiLab DLL parametro Pointer






function ApriOpenDialog: ShortString;
var pannello: TOpenDialog;
begin
   pannello :=  TOpenDialog.Create(nil);
   if pannello.Execute then
      result := pannello.FileName
   else
      result := '';
end;



function NumInputs: Byte;
begin
   result := Inputs; // trasferire quantita entrata
end;



function NumOutputs: Byte;
begin
   result := Outputs; // trasferire quantita uscita
end;




function InputName(Channel: Byte): ShortString; // trasferire nome di entrata

begin
   case Channel of
    I0 : result := 'I0'; // nome di pin I0
    I1 : result := 'I1'; // nome di pin I1
   end;
end;




Function OutputName(Channel: Byte): ShortString; // trasferire nome di uscita

begin
   case Channel of
    Q0 : result := 'Q0'; // nome di pin Q0
    Q1 : result := 'Q1'; // nome di pin Q1
   end;
end;


Procedure SimStart(PInput,POutput,PUser: PDLLParams); // Routine viene eseguita solo al primo avvio

begin
  // solo per inizializzare
end;


Procedure Calculate(PInput,POutput,PUser: PDLLParams); // Routine è permanente

   var s: ShortString;

   begin

       // Apri la finestra di dialogo TOpendialog
       s :=ApriOpenDialog;

       // poi valorizzi
       PInput^[I0] :=ApriOpenDialog;

      // piu funzioni

end;


Procedure SimStop(PInput,POutput,PUser: PDLLParams); // Routine viene eseguita solo in fase di chiusura

begin
   // solo in chiusura
end;


//export methods for ProfiLab
exports SimStart,
         SimStop,
         NumInputs,
         NumOutputs,
         Calculate,
         InputName,
         OutputName,
         ApriOpenDialog;

begin
end. 
Titolo: Re:DLL con SaveDialog
Inserito da: Simon75 - Dicembre 21, 2012, 11:11:54 am
Aggiungo un esempio di dll counter creato dalla casa del software che uso:

Codice: [Seleziona]

library Counter;
 
// Delphi 5 DLL-source (COUNTER.DLL)
// Defines a simple 8-Bit counter component for ProfiLab
 
uses
  SysUtils,Windows,Classes;
 
{$R *.RES}
 
Const  Inputs = 2;  // number of inputs
       Outputs = 8; // number of outputs
 
       {INPUTS}
       CLK   = 0;   // index of input variable CLK
       RST   = 1;   // index of input variable RST
 
       {OUTPUTS}
 
       {USER}
       CLK_old = 0; // index user variable CLK_old
       RST_old = 1; // index user variable RST_old
       Count = 2;   // index user variable COUNT
 
Type TDLLParams = array[0..100] of extended;   //Type of ProfiLab DLL parameters
     PDLLParams = ^TDLLParams;                 // Pointer to ProfiLab DLL parameters
 
function NumInputs: Byte;
begin
  result:=Inputs; //Define number of component input pins
end;
 
function NumOutputs: Byte;
begin
  result:=Outputs; //Define number of component output pins
end;
 
Function InputName(Channel: Byte): ShortString; // Return name for each component input pin
begin
   case Channel of
   CLK: result:='CLK';   //  "CLK" (Clock)
   RST: result:='/RST';  //  "/RST" (NOT RESET)
   end;
end;
 
Function OutputName(Channel: Byte): ShortString; // Return name for each component output pin
begin
   result:='Q'+intToStr(Channel); //"Q0".."Q7" (Binary count)
end;
 
Procedure SimStart(PInput,POutput,PUser: PDLLParams); //called when ProfiLab enters RUN mode
var i: Integer;
begin
   PUser^[Count]:=0; //RESET COUNTER
   For i:=0 to Outputs do
   begin
       POutput[i]:=0; //Set binary outputs with COUNT=0
   end;
end;
 
Procedure SimStop(PInput,POutput,PUser: PDLLParams); //called when ProfiLab RUN mode is terminated
begin
  // nothing to be done
end;
 
Procedure Calculate(PInput,POutput,PUser: PDLLParams); //called regularly from ProfiLab
var i: Integer;
begin
   if PInput^[RST]<2.5 then //check RST input HIGH or LOW
   begin
      if (not (PInput^[RST]>=2.5)) and (PUser^[RST_old]>2.5) then //check out falling edge at RST input
      begin
         PUser^[Count]:=0; //RESET COUNT
         For i:=0 to Outputs do
         begin
             POutput[i]:=0; //Set binary outputs with COUNT=0
         end;
      end;
      exit;
   end;
   PUser^[RST_old]:=PInput^[RST]; //Remember RST status for next call
 
   if PInput^[CLK]>2.5 then //check CLK input HIGH or LOW
   begin
      if (PInput^[CLK]>2.5) and not(PUser^[CLK_old]>2.5) then //check out rising edge at CLK input
      begin
         PUser^[Count]:=PUser^[Count]+1; // increase COUNT
         if PUser^[Count]>255 then PUser^[Count]:=0; //check overflow
         For i:=0 to Outputs do
         begin
            if (round(PUser^[Count]) and (1 shl i))>0 then POutput^[i]:=5 else POutput[i]:=0; //Set binary outputs with current COUNT
         end;
      end;
   end;
   PUser^[CLK_old]:=PInput^[CLK]; //Remember CLK status for next call
end;
 
 
//export methods for ProfiLab
exports SimStart,
        SimStop,
        NumInputs,
        NumOutputs,
        Calculate,
        InputName,
        OutputName;
 
begin
end.

Titolo: Re:DLL con SaveDialog
Inserito da: Stilgar - Dicembre 22, 2012, 03:14:48 pm
Codice: [Seleziona]
type TStringParams = array[0..100] of PChar;
     PStringParams = ^TStringParams;
Diventa
Codice: [Seleziona]
Type TDLLParams = array[0..100] of PChar; // ProfiLab DLL parametro Type
      PDLLParams = ^TDLLParams ;               // ProfiLab DLL parametro Pointer
Occhio che devi usare le funzioni stringa per la gestione delle stringhe open via pchar.
Le allochi.
Le azzeri (il puntato, non il puntatore).
Le copi.

Se hai problemi a questo livello, ti consiglio di lasciar perdere il simulatore/emulatore o quel cavolo che è, per una attimino. Fatti una bella lettura della sezione HowTo.
xinyiman saprà indicarti gli howto più adatti.

Se alcuni concetti non ti sono chiari, qui ci sono molte persone disponibili ad aiutarti. Da quello che ho capito hai forti lacune sulla programmazione pascal/object pascal. Spiegarle in un thread specifico non lo trovo molto d'aiuto.

Stilgar
Titolo: Re:DLL con SaveDialog
Inserito da: Simon75 - Dicembre 23, 2012, 06:06:40 pm
Ciao Stilgar,
Sai dirmi cosa vuol dire questo?

Codice: [Seleziona]
project1.lpr(0,0) Fatal: Can not find unit Interfaces used by project1. Check if package LCL is in the dependencies.

Non riesco a compilare
Dove posso trovare un manuale per principianti?

Ma per far aprire questa benedetta finestra quando clicco sopra ci vuole ancora molto ? :)
possibile che è così lunga?
Ho bisogno di una vostra mano...se possibile
Ringrazio tutti
Ciao ;)
Titolo: Re:DLL con SaveDialog
Inserito da: Stilgar - Dicembre 23, 2012, 06:27:56 pm
Controlla le dipendenze del progetto.
Devi fare in modo che il linker "agganci" le librerie grafiche per far aprire la finestr a di dialogo.

Controlla cosa viene "aggiunto" tramite il menù:
Progetto->Analizza Progetto

Cerca nella sezione "pacchetti richiesti" LCL.
Se non la trovi, clicca sul "+" e crea la nuova dipendenza.
(Nuovo requisito)
Titolo: Re:DLL con SaveDialog
Inserito da: Simon75 - Dicembre 23, 2012, 07:12:43 pm
Ho aperto Analizzatore progetti e dentro ho File, project1.lpr e pacchetto richiesto....
cliccando su pacchetto richiesto non accade nulla se poi devo aggiungere qualcosa cosa aggiungo?
Ciao
Titolo: Re:DLL con SaveDialog
Inserito da: Stilgar - Dicembre 23, 2012, 07:16:04 pm
LCL
Titolo: Re:DLL con SaveDialog
Inserito da: Simon75 - Dicembre 23, 2012, 07:34:13 pm
Grazie Stilgar almeno questo sono riuscito a farlo ;)
Ma ora mi genera questo errore:
Codice: [Seleziona]

project1.lpr(100,20) Hint: Parameter "PInput" not used
project1.lpr(100,27) Hint: Parameter "POutput" not used
project1.lpr(100,35) Hint: Parameter "PUser" not used
project1.lpr(117,22) Error: Incompatible types: got "ShortString" expected "PChar"
project1.lpr(145) Fatal: There were 1 errors compiling module, stopping

type l'ho modificato così:

Codice: [Seleziona]

type TDLLParams = array[0..100] of PChar;
     PDLLParams = ^TDLLParams;       

Grazie
Titolo: Re:DLL con SaveDialog
Inserito da: Stilgar - Dicembre 23, 2012, 11:35:45 pm
Codice: [Seleziona]
project1.lpr(117,22) Error: Incompatible types: got "ShortString" expected "PChar"
Questo?
Titolo: Re:DLL con SaveDialog
Inserito da: Simon75 - Dicembre 23, 2012, 11:37:21 pm
si quello
Titolo: Re:DLL con SaveDialog
Inserito da: Stilgar - Dicembre 23, 2012, 11:39:35 pm
Cosa ti ho indicato per
Codice: [Seleziona]
project1.pas(116,23) Error: Incompatible types: got "ShortString" expected "Extended"
Lo ricordi?
Codice: [Seleziona]
type TStringParams = array[0..100] of PChar;
     PStringParams = ^TStringParams;
Diventa
Codice: [Seleziona]
Type TDLLParams = array[0..100] of PChar; // ProfiLab DLL parametro Type
      PDLLParams = ^TDLLParams ;               // ProfiLab DLL parametro Pointer
Occhio che devi usare le funzioni stringa per la gestione delle stringhe open via pchar.
Le allochi.
Le azzeri (il puntato, non il puntatore).
Le copi.

Se hai problemi a questo livello, ti consiglio di lasciar perdere il simulatore/emulatore o quel cavolo che è, per una attimino. Fatti una bella lettura della sezione HowTo.
xinyiman saprà indicarti gli howto più adatti.

Se alcuni concetti non ti sono chiari, qui ci sono molte persone disponibili ad aiutarti. Da quello che ho capito hai forti lacune sulla programmazione pascal/object pascal. Spiegarle in un thread specifico non lo trovo molto d'aiuto.

Stilgar
Titolo: Re:DLL con SaveDialog
Inserito da: Simon75 - Dicembre 23, 2012, 11:46:03 pm
Scusami Stilgar abbi pazienza ma non capisco questa:

Occhio che devi usare le funzioni stringa per la gestione delle stringhe open via pchar.
Le allochi.
Le azzeri (il puntato, non il puntatore).
Le copi.
Titolo: Re:DLL con SaveDialog
Inserito da: Stilgar - Dicembre 23, 2012, 11:56:54 pm
... stai usando delle Short String.
Sono stringhe che al massimo contengono 255 caratteri. Il carattere 0 non è indirizzabile/modificabile perchè viene usato dal compilatore per la gestione della lunghezza.
Esistono le stringhe open, sono stringhe che possono raggiungere i 4gb (vado a memoria, ma non giocarti la casa su sto numero) di lunghezza. Usano un carattere detto null char (0x00) come tappo alla fine della stringa. Sono le stesse che usa il c++/c come convenzione.

Usando il PChar, stai dichiarando esplicitamente che vuoi un puntatore a Stringa Ansi. Ovvero un puntatore a carattere. (Le stringhe sono una convenzione dei programmatori, per il compilatore/computer sono solo una sequenza di caratteri adiacenti senza alcun significato particolare).
Quando gestisci una stringa open (o puntatore a carattere) hai tutto l'onere della gestione della memoria.

1) Quindi fai una bella "new" della zona di memoria che ti serve, chiedi al sistema operativo di assegnarti della ram.
2) Fai un ciclo for per la copia dei singoli caratteri dentro la zona di memoria che hai allocato in precedenza.

Esistono anche altri modi, ma visto che sei in un ambiente eterogeneo, non te le consiglio.
Meglio chiedere al sistema operativo la ram e non farla pesacare dall'heap allocato da FreePascal. Potrebbero esserci dei comportamenti "bislacchi" del programma. Ti funziona 2 volte su 3 per capici.

Stilgar
Titolo: Re:DLL con SaveDialog
Inserito da: Simon75 - Dicembre 24, 2012, 12:06:18 am
Ok poiché non so da dove partire, (sinceramete pensavo fosse più semplice :) )dove mi consigli di studiare?

Forse dopo qualche mese sarò capace ;)

1) Quindi fai una bella "new" della zona di memoria che ti serve, chiedi al sistema operativo di assegnarti della ram.
2) Fai un ciclo for per la copia dei singoli caratteri dentro la zona di memoria che hai allocato in precedenza

Ciao
Grazie
Titolo: Re:DLL con SaveDialog
Inserito da: Simon75 - Dicembre 26, 2012, 02:21:47 pm
Ciao a tutti e Buon Natale;
Ho risolto con la OpenDialog, appena premo un pulsante dal mio software si apre la OpenDialog, ma ci sono dei problemini: come mai quando la apro poi non riesco più a chiuderla? e perché quando tento di aprire un file txt non lo apre?
Ho il presentimento che devo mdificare la funzione giusto?
vi ringrazio molto
Ciao
Codice: [Seleziona]
     function ApriOpenDialog: ShortString;
     var pannello: TOpenDialog;
     begin
        pannello := TOpenDialog.Create(nil);
        if pannello.Execute then
           result := pannello.FileName
        else
           result := '';
     end;       


(http://i46.tinypic.com/2itlyra.png)
Titolo: Re:DLL con SaveDialog
Inserito da: Stilgar - Dicembre 26, 2012, 08:59:33 pm
Strano che all'execute apra il dialogo ma alla pressione di "apri" non chiuda il dialogo.
Notavo che non hai configurato i filtri del dialogo, per cui prende *.* come default.
Se scatta l'execute e non chiude la finestra, prova a chiamare la "destroy" del dialogo, in modo da "killarlo" a mano.
Poi il file non lo apre mica il dialogo, devi essere tu (una volta che hai il nome da usare) leggere il contenuto ... mica lo fa da solo ...

Stilgar
Titolo: Re:DLL con SaveDialog
Inserito da: Simon75 - Dicembre 26, 2012, 09:24:14 pm
Ciao, anche se clicco sulla X si chiude e si riapre velocemente, come la richiamo la destroy? non ho idea.
Stilgard ma puoi spiegarmi come mai non posso cambiare il (nil) e mettere un (self)?
Filter l'ho inserito e funziona ;)

Codice: [Seleziona]

function ApriOpenDialog: ShortString;
var pannello: TOpenDialog;
begin
   pannello :=  TOpenDialog.Create(nil);
   pannello.Filter:='*.txt';
   if pannello.Execute then
      result := pannello.FileName
   else
      result := '';
end;       
 
Ma una volta che trovo un file txt da aprire lui non lo apre se ci clicco sopra?
Come posso fare?
Titolo: Re:DLL con SaveDialog
Inserito da: Stilgar - Dicembre 26, 2012, 10:00:32 pm
mmm.
Prova a fare in modo che una funzione (dentro la DLL) conteggi il numero di volte che viene chiamata.
E faccia vedere il numero a video.
Ho il sospetto che la DLL esponga delle funzioni e queste vengano chiamate di continuo....
Per cui la cosa che stai facendo è da impostare diversamente ... (ma non conosco ProfiLab)
Titolo: Re:DLL con SaveDialog
Inserito da: Simon75 - Dicembre 26, 2012, 10:42:47 pm
Una delle tante cose che non capisco è come mai Lazarus genera una dll da 13,8 MB  :o
Titolo: Re:DLL con SaveDialog
Inserito da: Simon75 - Dicembre 27, 2012, 12:02:18 am
Allora nelle modifiche che ho fatto ho rimesso Extended quindi non dovrebbero esserci problemi, poi in Procedure Calculate ho risolto così si aprono sia OpenDialog che SaveDialog, ma non si chiudono.
Sui 2 ingressi ho messo i controlli poiché il pulsante della mi libreria nel momento che viene premuto genera un 5V quindi si spiega il perché si apre... ma non si spiega il perché non si chiude...
Ciao

Codice: [Seleziona]

Procedure Calculate(PInput,POutput,PUser: PDLLParams); // Routine è permanente



   begin

       if  PInput^[I0] > 2.5 then ApriOpenDialog;
       if  PInput^[I1] > 2.5 then ApriSaveDialog;


      // piu funzioni


end;




Codice: [Seleziona]

library dialog;

{$mode objfpc}{$H+}

uses
   Interfaces, Classes, SysUtils, Windows, FileUtil, Forms, Controls,
Graphics, Dialogs;
   { you can add units after this }


// questa direttiva l'ho tolta perchè non mi creava la dll, mi sono documentato sul forum lazarus {$R *.RES}




Const  Inputs = 2;  // quantita entrata
        Outputs = 2; // quantita uscita

        {INPUTS}  // nome per numero di entrata
         I0 = 0;  // valore I0 = PInput[I0] ossia PInput[0]
         I1 = 1;  // valore I1 = PInput[I1] ossia PInput[1]
      // I2 = 2;
      // I3 = 3;
// ... I99 = 99;

        {OUTPUTS} // nome per numero di uscita
         Q0 = 0;  // valore Q0 = POutput[Q0] ossia POutput[0]
         Q1 = 1;  // valore Q1 = POutput[Q1] ossia POutput[1]
      // Q2 = 2;
      // Q3 = 3;
// ... Q99 = 99;

        {USER}   // nome per numero di variabile, I valori vengono memorizzati

         U0 = 0; // valore U0 = PUser[U0] ossia PUser[0]
      // U1 = 1;
      // U2 = 2;
      // U3 = 3;
// ... U99 = 99;

// I0,I1,I2,I3,Q0,Q1,Q2,Q3,U0,U1,U2,U3
// I nomi possono essere qualsiasi, sono case-insensitive

type TDLLParams = array[0..100] of Extended; //Type of ProfiLab DLL parameters
     PDLLParams = ^TDLLParams;               // Pointer to ProfiLab DLL parameters

     function ApriSaveDialog: ShortString;
     var pannello: TSaveDialog;
     begin
       pannello :=TSaveDialog.Create(nil);
       pannello.Filter:='*.txt';
       if pannello.Execute then
          result := pannello.FileName
   else
      result := '';


     end;


function ApriOpenDialog: ShortString;
var pannello: TOpenDialog;
begin
   pannello :=  TOpenDialog.Create(nil);
   pannello.Filter:='*.txt';
   if pannello.Execute then
      result := pannello.FileName
   else
      result := '';
end;



function NumInputs: Byte;
begin
   result := Inputs; // trasferire quantita entrata
end;



function NumOutputs: Byte;
begin
   result := Outputs; // trasferire quantita uscita
end;




function InputName(Channel: Byte): ShortString; // trasferire nome di entrata

begin
   case Channel of
    I0 : result := 'I0'; // nome di pin I0
    I1 : result := 'I1'; // nome di pin I1
   end;
end;




Function OutputName(Channel: Byte): ShortString; // trasferire nome di uscita

begin
   case Channel of
    Q0 : result := 'Q0'; // nome di pin Q0
    Q1 : result := 'Q1'; // nome di pin Q1
   end;
end;


Procedure SimStart(PInput,POutput,PUser: PDLLParams); // Routine viene eseguita solo al primo avvio

begin
  // solo per inizializzare
end;


Procedure Calculate(PInput,POutput,PUser: PDLLParams); // Routine è permanente



   begin

       if  PInput^[I0] > 2.5 then ApriOpenDialog;
       if  PInput^[I1] > 2.5 then ApriSaveDialog;


      // piu funzioni


end;


Procedure SimStop(PInput,POutput,PUser: PDLLParams); // Routine viene eseguita solo in fase di chiusura

begin
   // solo in chiusura
end;


//export methods for ProfiLab
exports SimStart,
         SimStop,
         NumInputs,
         NumOutputs,
         Calculate,
         InputName,
         OutputName,
         ApriOpenDialog,
         ApriSaveDialog;
begin
end. 
 
Titolo: Re:DLL con SaveDialog
Inserito da: nomorelogic - Dicembre 27, 2012, 12:24:27 pm
Una delle tante cose che non capisco è come mai Lazarus genera una dll da 13,8 MB  :o

prova a dare un'occhiata qua
http://www.lazarus.freepascal.org/index.php?topic=7590.0 (http://www.lazarus.freepascal.org/index.php?topic=7590.0)
Titolo: Re:DLL con SaveDialog
Inserito da: nomorelogic - Dicembre 27, 2012, 12:39:39 pm
Allora nelle modifiche che ho fatto ho rimesso Extended quindi non dovrebbero esserci problemi, poi in Procedure Calculate ho risolto così si aprono sia OpenDialog che SaveDialog, ma non si chiudono.
Sui 2 ingressi ho messo i controlli poiché il pulsante della mi libreria nel momento che viene premuto genera un 5V quindi si spiega il perché si apre... ma non si spiega il perché non si chiude...

Non so perchè non si chiudono ma c'è un errore abbastanza serio nelle definizioni delle funzioni ApriSaveDialog e ApriOpenDialog.
Nel codice da te postato c'è la creazione dell'istanza ma non c'è la liberazione delle risorse. Questo vuol dire che ogni volta che invochi una di queste funzioni, viene allocata della memoria ma nessuno si preoccupa di restituirla al sistema.
La differenza nella gestione della memoria tra un componente messo su un form a design-time ed uno istanziato a run-time è che:

quindi la tua funzione dovrebbe diventare così:

Codice: [Seleziona]
function ApriOpenDialog: ShortString;
var pannello: TOpenDialog;
begin
   pannello :=  TOpenDialog.Create(nil);
   try
      pannello.Filter:='*.txt';
      if pannello.Execute then
         result := pannello.FileName
      else
         result := '';
   finally
      pannello.Free;
   end;

Appena dopo la creazione, in casi come questi, ti consiglio di inserire sempre un blocco try...finally e di mettere nel finally la liberazione delle risorse.
Questo ti mette al riparo da eventuali crash e/o eccezioni e se la tua applicazione dovesse anche subire un arresto non previsto, avresti sempre la certezza di aver liberato la memoria istanziata a run-time.

Ho anche la sensazione che così i dialog potrebbero chiudersi ;)
Titolo: Re:DLL con SaveDialog
Inserito da: Stilgar - Dicembre 27, 2012, 03:10:11 pm
Una delle tante cose che non capisco è come mai Lazarus genera una dll da 13,8 MB  :o

prova a dare un'occhiata qua
http://www.lazarus.freepascal.org/index.php?topic=7590.0 (http://www.lazarus.freepascal.org/index.php?topic=7590.0)

Nomore. A volte non capisco se nel forum principale c'è gente che riceve soldi dai produttori di dischi o ISP. Sprecano risorse come se fossero gratis. A questi cascare in un cluod insegnerebbe che ogni virgola ha un costo.
Sarà che io sono cresciuto con un turbo modem (56.6k) e mi sentivo un signore. Ora con connessioni più veloci, ti ritrovi che non basta la banda ...

Simon, il ".free" serve a liberare memoria.
Facci sapere se è sufficiente, altrimenti mi è già venuta in mente un'altra modifica al codice ... ;)
Titolo: Re:DLL con SaveDialog
Inserito da: nomorelogic - Dicembre 27, 2012, 04:01:53 pm
Citazione
Nomore. A volte non capisco se nel forum principale c'è gente che riceve soldi dai produttori di dischi o ISP. Sprecano risorse come se fossero gratis. A questi cascare in un cluod insegnerebbe che ogni virgola ha un costo.
Sarà che io sono cresciuto con un turbo modem (56.6k) e mi sentivo un signore. Ora con connessioni più veloci, ti ritrovi che non basta la banda ...

in effetti questa è una cosa che non ho mai capito...
lasciare nel binario finale le info superflue ma che servono al debug mi può andare anche bene; dover vagare come un rabdomante per capire come rendere normali le dimensioni di un binario da distribuire: no!

speriamo se ne accorgano presto che nell'IDE non c'è un'opzione per ovviare alla cosa...
Titolo: Re:DLL con SaveDialog
Inserito da: Stilgar - Dicembre 27, 2012, 04:17:10 pm
Naaa, hai presente il discorso che abbiamo fatto con il crucco sulla necessità di ricompilare l'ide al bisogno? Visto che a me la Wind blocca il repo svn di freepascal.
Ha detto che visto che si può, si fà. Non vede il problema ....
(Io spero che la moglie non la pensi come lui, visto che se si trova nella possibilità di renderlo cervo, lo farà perchè si può farlo).
Titolo: Re:DLL con SaveDialog
Inserito da: nomorelogic - Dicembre 27, 2012, 04:47:47 pm
:D
Titolo: Re:DLL con SaveDialog
Inserito da: Simon75 - Dicembre 27, 2012, 11:03:08 pm
Ciao
Ho tolto SaveDialog per una prova più mirata:)
Ma genera questo errore:

Codice: [Seleziona]

project1.lpr(65,1) Error: Illegal expression
project1.lpr(65,10) Fatal: Syntax error, ";" expected but "identifier NUMINPUTS" found



Esattamente su qesta riga e non capisco il perché se prima andava bene:)

Codice: [Seleziona]
function NumInputs: Byte;               <--------------questa riga
begin
   result := Inputs; // trasferire quantita entrata
end; 


Codice: [Seleziona]






library dialog;

{$mode objfpc}{$H+}

uses
   Interfaces, Classes, SysUtils, Windows, FileUtil, Forms, Controls,
Graphics, Dialogs;
   { you can add units after this }




Const  Inputs = 2;  // quantita entrata
        Outputs = 2; // quantita uscita

        {INPUTS}  // nome per numero di entrata
         I0 = 0;  // valore I0 = PInput[I0] ossia PInput[0]
         I1 = 1;  // valore I1 = PInput[I1] ossia PInput[1]
      // I2 = 2;
      // I3 = 3;
// ... I99 = 99;

        {OUTPUTS} // nome per numero di uscita
         Q0 = 0;  // valore Q0 = POutput[Q0] ossia POutput[0]
         Q1 = 1;  // valore Q1 = POutput[Q1] ossia POutput[1]
      // Q2 = 2;
      // Q3 = 3;
// ... Q99 = 99;

        {USER}   // nome per numero di variabile, I valori vengono memorizzati

         U0 = 0; // valore U0 = PUser[U0] ossia PUser[0]
      // U1 = 1;
      // U2 = 2;
      // U3 = 3;
// ... U99 = 99;

// I0,I1,I2,I3,Q0,Q1,Q2,Q3,U0,U1,U2,U3
// I nomi possono essere qualsiasi, sono case-insensitive

type TDLLParams = array[0..100] of Extended; //Type of ProfiLab DLL parameters
     PDLLParams = ^TDLLParams;               // Pointer to ProfiLab DLL parameters




function ApriOpenDialog: ShortString;
var pannello: TOpenDialog;
begin
   pannello :=  TOpenDialog.Create(nil);
   try
      pannello.Filter:='*.txt';
      if pannello.Execute then
         result := pannello.FileName
      else
         result := '';
   finally
      pannello.Free;
   end;





function NumInputs: Byte;
begin
   result := Inputs; // trasferire quantita entrata
end;



function NumOutputs: Byte;
begin
   result := Outputs; // trasferire quantita uscita
end;




function InputName(Channel: Byte): ShortString; // trasferire nome di entrata

begin
   case Channel of
    I0 : result := 'I0'; // nome di pin I0
    I1 : result := 'I1'; // nome di pin I1
   end;
end;




Function OutputName(Channel: Byte): ShortString; // trasferire nome di uscita

begin
   case Channel of
    Q0 : result := 'Q0'; // nome di pin Q0
    Q1 : result := 'Q1'; // nome di pin Q1
   end;
end;


Procedure SimStart(PInput,POutput,PUser: PDLLParams); // Routine viene eseguita solo al primo avvio

begin
  // solo per inizializzare
end;


Procedure Calculate(PInput,POutput,PUser: PDLLParams); // Routine è permanente



   begin

       if  PInput^[I0] > 2.5 then ApriOpenDialog;
       if  PInput^[I1] > 2.5 then ApriSaveDialog;


      // piu funzioni


end;


Procedure SimStop(PInput,POutput,PUser: PDLLParams); // Routine viene eseguita solo in fase di chiusura

begin
   // solo in chiusura
end;


//export methods for ProfiLab
exports SimStart,
         SimStop,
         NumInputs,
         NumOutputs,
         Calculate,
         InputName,
         OutputName,
         ApriOpenDialog,
         ApriSaveDialog;
begin
end.       
Titolo: Re:DLL con SaveDialog
Inserito da: Stilgar - Dicembre 27, 2012, 11:49:58 pm
Controlla gli end della funzione prima ...
Codice: [Seleziona]
begin
   pannello :=  TOpenDialog.Create(nil);
   try
      pannello.Filter:='*.txt';
      if pannello.Execute then
         result := pannello.FileName
      else
         result := '';
   finally
      pannello.Free;
   end;

function NumInputs: Byte;

Credo che il compilatore stia cercando di dirti che per lui manca un end per fare quello che vuoi tu ;)
Titolo: Re:DLL con SaveDialog
Inserito da: Simon75 - Dicembre 27, 2012, 11:57:12 pm
Che Asino che sono :)
Ma scusa perché ci vanno due end;
per i controlli?
Grazie Stilgard sei sempre presente  ;)
Titolo: Re:DLL con SaveDialog
Inserito da: Stilgar - Dicembre 28, 2012, 12:01:03 am
Ogni blocco ha un inizio e una fine.
Codice: [Seleziona]
begin <-inizio blocco
   pannello :=  TOpenDialog.Create(nil);
   try <-inizio blocco
      pannello.Filter:='*.txt';
      if pannello.Execute then
         result := pannello.FileName
      else
         result := '';
   finally
      pannello.Free;
   end;<-fine blocco try finally end
end; <- fine blocco begin end
Titolo: Re:DLL con SaveDialog
Inserito da: nomorelogic - Dicembre 28, 2012, 01:25:55 am
mea culpa
mi sa tanto che quando ho copia/incollato ci ho lasciato l'ultimo "end;"
Titolo: Re:DLL con SaveDialog
Inserito da: Simon75 - Dicembre 28, 2012, 02:32:15 am
nomorelogic grazie funziona molto meglio ma vi saprò dire di più domani, anzi oggi visto l'orario   ;D.
Ma se dovessi far accendere un led sull'uscita della mi dll dovrei creare un altra funzione e poi richiamarla in procedure ?
Vi ringrazio per quello che mi state insegnando.
Ciao
Titolo: Re:DLL con SaveDialog
Inserito da: Simon75 - Dicembre 28, 2012, 11:08:29 pm
Ciao

Allora si aprono e si chiudono bene ma a volte rimane premuto il pulsante e quindi non mi fa chiudere la OpenDialog lo stesso capita per la SaveDialog.
Attualmente ho inserito questi controlli in procedure Calculate per garantire la chiusura qundo non lo chiamo.
E poi come prova ho inserito 2 LED sulle ripettive uscite, quindi quando viene premuto il pulsante della OpenDialog si deve accendere un led, se viene premuto il pulsante della SaveDialog si deve accendere l'altro LED.
Ha funzionato ma poi non l'ho visto più accendere.

è giusto come ho scritto?

Codice: [Seleziona]

Procedure Calculate(PInput,POutput,PUser: PDLLParams); // Routine è permanente


   begin

       if  PInput^[I0] >2.5 then ApriOpenDialog
       else PInput^[I0]:=0;
       if  PInput^[I1] >2.5 then ApriSaveDialog
       else PInput^[I1]:=0;
       If  PInput^[I0] >2.5 then POutput^[Q0]:=5
         else POutput^[Q0]:=0;
        If  PInput^[I1] >2.5 then POutput^[Q1]:=5 
       else POutput^[Q1]:=0;

       // accende il led quando viene premuto PInput^[I0] ovvero OpenDilog
       // accende il led quando viene premuto PInput^[I1] ovvero SaveDialog
   

   // piu funzioni


end;   



(http://i49.tinypic.com/103da8m.jpg)
Titolo: Re:DLL con SaveDialog
Inserito da: Simon75 - Dicembre 28, 2012, 11:45:06 pm
Così funziona ho dovuto togliere gli else
 quindi:

Codice: [Seleziona]

Procedure Calculate(PInput,POutput,PUser: PDLLParams); // Routine è permanente


   begin

       if  PInput^[I0] >2.5 then ApriOpenDialog;

       if  PInput^[I1] >2.5 then ApriSaveDialog;

       If  PInput^[I0] >2.5 then POutput^[Q0]:=5;

        If  PInput^[I1] >2.5 then POutput^[Q1]:=5;



      // piu funzioni


end;

Ma rimane sempre il problema che a volte si bloccano i pulsanti se clicco veloce si apre e si chiude regolare, basta che lo tengo un po troppo premuto si blocca

Titolo: Re:DLL con SaveDialog
Inserito da: Stilgar - Dicembre 29, 2012, 12:01:08 am
Il fatto che si blocchi, può avere varie cause.
1) Il programma si impalla di suo.
2) La dll si incasina con la creazione e distruzione del dialogo.

Metti i vari dialoghi in una variabile "globale".
Controlli se la variabile è già stata istanziate
Codice: [Seleziona]
 
  if not assigned(dialogoxxx) then
  begin
    dialogoxxx := TDialog.create(...);
    ...
    FreeAndNil(dialogxxx);
  end;
In questo modo il codice apre il dialogo solo se non è già stato aperto.
Quindi la variabile del dialogo ti funge da ... "semaforo".

Stilgar
Titolo: Re:DLL con SaveDialog
Inserito da: Simon75 - Dicembre 29, 2012, 09:58:31 pm
Domanda n 1

Allora quando apro uno dei due dialoghi si accende il led rispettivo al diagolo chiamato, ma quando clicco su annulla o sulla x i led rimangono sempre accesi.
Domanda: come faccio a resettare il controllo ovvero l'uscita POutput^[Q0] quando clicco su annulla o sulla X dei dialoghi?
Codice: [Seleziona]
 If  PInput^[I0] >2.5 then POutput^[Q0]:=5;

Domanda n2

Ho tolto le variabili locali e le ho messe globali, praticamente solo una poiché è la stessa.
Codice: [Seleziona]

 var pannello: TOpenDialog;


type TDLLParams = array[0..100] of Extended; //Type of ProfiLab DLL parameters
     PDLLParams = ^TDLLParams;               // Pointer to ProfiLab DLL parameters





     function ApriSaveDialog: ShortString;

     begin
        pannello :=  TSaveDialog.Create(nil);
        try
           pannello.Filter:='*.txt';
           if pannello.Execute then
              result := pannello.FileName
           else
              result := '';
        finally
           pannello.Free;
        end;
        end;


function ApriOpenDialog: ShortString;

begin
   pannello :=  TOpenDialog.Create(nil);
   try
      pannello.Filter:='*.txt';
      if pannello.Execute then
         result := pannello.FileName
      else
         result := '';
   finally
      pannello.Free;
   end;
   end;
 

Ora il codice che mi hai indicato lo devo inserire in Calculate?

Codice: [Seleziona]
Procedure Calculate(PInput,POutput,PUser: PDLLParams); // Routine è permanente
   
if not assigned (ApriOpenDialog) then

   begin

ApriOpenDialog:= TDialog.create(...); qua cosa metto?       
...         qui cosa metto?
    FreeAndNil(ApriOpenDialog);

  end;


      // piu funzioni


end;                                   


Domanda n 3

Esiste un modo per evitare che la schermata del dialogo vada sotto il programma che sto usando?
Cerco di spiegarmi a volte capita che clicco fuori dalla finestra di dialogo e quindi il dialogo a sua volta finisce sul desktop quindi sotto il programma allora devo chiudere sulla - per riprenderlo e chiuderlo

Ciao
Titolo: Re:DLL con SaveDialog
Inserito da: Stilgar - Dicembre 30, 2012, 11:52:31 am
Risposta 1 :
Codice: [Seleziona]
POutput^[Q0]:=0;
If  PInput^[I0] >2.5 then POutput^[Q0]:=5;

Risposta 2:
Esattamente la stessa cosa in entrambe le funzioni. Solo che una è chiamata dal primo pulsante e l'altra dal secondo ... ma se fanno la stessa cosa, potrebbe essere il caso di avere una sola funzione... no?

Risposta 3:
Il dialogo, per essere modale ha bisogno di una finestra "padre", mettendo nil, dici che non ha padre ed è autonoma, per cui non può essere modale sull'applicazione chiamante.
Per fare in modo che abbia un "padre", devi avere un'istanza dell'applicazione chimanate (in genere è nella "main dll" che ti viene passato quel parametro, ma in freepascal non conosco la prassi per lavorare con questi parametri, in C++ della Microsoft è una cosa "abbastanza semplice")
Titolo: Re:DLL con SaveDialog
Inserito da: Stilgar - Dicembre 30, 2012, 11:55:39 am
Per la prima risposta ... piccola cazzatina, ho messo in pulldown il dato ... tu lo lasciavi flottante, ma in informatica è l'ultima scrittura che comanda il dato in memoria. Nessuno azzera quella cella (se non all'inizio il sistema di inizializzazione automatica), per cui l'effetto è di lasciare il led acceso.
Sempre che sia riuscito ad interpretare correttamente il comportamento che ottenevi.

Stilgar
Titolo: Re:DLL con SaveDialog
Inserito da: Simon75 - Dicembre 30, 2012, 04:54:07 pm
Citazione

Per la prima risposta ... piccola cazzatina


Così semplice che neanche si accendono i led se metto questo: ;D ;D ;D ;D ;D
Codice: [Seleziona]

POutput^[Q0]:=0;


Stilgard dovrebbero promuoverti super moderatore, poiché sei il più attivo di tutto il forum  ;)
Titolo: Re:DLL con SaveDialog
Inserito da: Stilgar - Dicembre 30, 2012, 07:20:13 pm
Allega tutto il codice ad un post ... sta diventando un macello seguire con i pezzetti l'evoluzione del sorgente :(
Titolo: Re:DLL con SaveDialog
Inserito da: Legolas - Dicembre 30, 2012, 09:09:19 pm
Infatti :)
Per sfizio ho scaricato la demo di ProfiLab, se Simon75 mette il codice della dll posso provare a buttarci un occhio anche io
Titolo: Re:DLL con SaveDialog
Inserito da: Simon75 - Dicembre 31, 2012, 12:33:53 am
Eccomi ecco il codice...                 


Codice: [Seleziona]

library dialog;

{$mode objfpc}{$H+}

uses
   Interfaces, Classes, SysUtils, Windows, FileUtil, Forms, Controls,
Graphics, Dialogs;
   { you can add units after this }




Const   Inputs = 2;  // quantita entrata
        Outputs = 2; // quantita uscita

        {INPUTS}  // nome per numero di entrata
         I0 = 0;  // valore I0 = PInput[I0] ossia PInput[0]
         I1 = 1;  // valore I1 = PInput[I1] ossia PInput[1]

      // I3 = 3;
// ... I99 = 99;

        {OUTPUTS} // nome per numero di uscita
         Q0 = 0;  // valore Q0 = POutput[Q0] ossia POutput[0]
         Q1 = 1;  // valore Q1 = POutput[Q1] ossia POutput[1]

      // Q3 = 3;
// ... Q99 = 99;

        {USER}   // nome per numero di variabile, I valori vengono memorizzati

         U0 = 0; // valore U0 = PUser[U0] ossia PUser[0]
      // U1 = 1;
      // U2 = 2;
      // U3 = 3;
// ... U99 = 99;

// I0,I1,I2,I3,Q0,Q1,Q2,Q3,U0,U1,U2,U3
// I nomi possono essere qualsiasi, sono case-insensitive





type TDLLParams = array[0..100] of Extended; //Type of ProfiLab DLL parameters
     PDLLParams = ^TDLLParams;               // Pointer to ProfiLab DLL parameters




     function ApriSaveDialog: ShortString;
     var pannello: TOpenDialog;
     begin
        pannello :=  TSaveDialog.Create(nil);
        try
           pannello.Filter:='*.txt';
           if pannello.Execute then
              result := pannello.FileName
           else
              result := '';
        finally
           pannello.Free;
        end;
        end;


function ApriOpenDialog: ShortString;
var pannello: TOpenDialog;
begin
   pannello :=  TOpenDialog.Create(nil);
   try
      pannello.Filter:='*.txt';
      if pannello.Execute then
         result := pannello.FileName
      else
         result := '';
   finally
      pannello.Free;
   end;
   end;





function NumInputs: Byte;
begin
   result := Inputs; // trasferire quantita entrata
end;



function NumOutputs: Byte;
begin
   result := Outputs; // trasferire quantita uscita
end;




function InputName(Channel: Byte): ShortString; // trasferire nome di entrata

begin
   case Channel of

    I0 : result := 'I0'; // nome di pin I0
    I1 : result := 'I1'; // nome di pin I1

   end;
end;




Function OutputName(Channel: Byte): ShortString; // trasferire nome di uscita

begin
   case Channel of
    Q0 : result := 'Q0'; // nome di pin Q0
    Q1 : result := 'Q1'; // nome di pin Q1

   end;
end;


Procedure SimStart(PInput,POutput,PUser: PDLLParams); // Routine viene eseguita solo al primo avvio

begin
  // solo per inizializzare
end;


Procedure Calculate(PInput,POutput,PUser: PDLLParams); // Routine è permanente

begin


       if  PInput^[I0] >2.5 then ApriOpenDialog;




       if  PInput^[I1] >2.5 then ApriSaveDialog;





       If  PInput^[I0] >2.5 then POutput^[Q0]:=5;





       If  PInput^[I1] >2.5 then POutput^[Q1]:=5;







end;                 // piu funzioni


Procedure SimStop(PInput,POutput,PUser: PDLLParams); // Routine viene es                                                            eguita solo in fase di chiusura

begin
   // solo in chiusura
end;


//export methods for ProfiLab
exports SimStart,
         SimStop,
         NumInputs,
         NumOutputs,
         Calculate,
         InputName,
         OutputName,
         ApriOpenDialog,
         ApriSaveDialog;
begin
end.

Titolo: Re:DLL con SaveDialog
Inserito da: Stilgar - Dicembre 31, 2012, 12:43:01 am
prova questo
Codice: [Seleziona]

library dialog;

{$mode objfpc}{$H+}

uses
  Interfaces,
  Classes,
  SysUtils,
  Windows,
  FileUtil,
  Forms,
  Controls,
  Graphics,
  Dialogs;

const
  Inputs = 2;  // quantita entrata
  Outputs = 2; // quantita uscita

  {INPUTS}// nome per numero di entrata
  I0 = 0;  // valore I0 = PInput[I0] ossia PInput[0]
  I1 = 1;  // valore I1 = PInput[I1] ossia PInput[1]

  // I3 = 3;
  // ... I99 = 99;

  {OUTPUTS}// nome per numero di uscita
  Q0 = 0;  // valore Q0 = POutput[Q0] ossia POutput[0]
  Q1 = 1;  // valore Q1 = POutput[Q1] ossia POutput[1]

  // Q3 = 3;
  // ... Q99 = 99;

  {USER}// nome per numero di variabile, I valori vengono memorizzati

  U0 = 0; // valore U0 = PUser[U0] ossia PUser[0]
  // U1 = 1;
  // U2 = 2;
  // U3 = 3;
  // ... U99 = 99;

  // I0,I1,I2,I3,Q0,Q1,Q2,Q3,U0,U1,U2,U3
  // I nomi possono essere qualsiasi, sono case-insensitive
var
  globalDialog: TFileDialog;

type
  TDLLParams = array[0..100] of extended; //Type of ProfiLab DLL parameters
  PDLLParams = ^TDLLParams;               // Pointer to ProfiLab DLL parameters



  function ApriSaveDialog: ShortString;
  begin
    if not assigned(globalDialog) then
    begin
      globalDialog := TSaveDialog.Create(nil);
      try
        globalDialog.Filter := '*.txt';
        if globalDialog.Execute then
          Result := globalDialog.FileName
        else
          Result := '';
      finally
        FreeAndNil(globalDialog);
      end;
    end;
  end;

  function ApriOpenDialog: ShortString;
  begin
    if not assigned(globalDialog) then
    begin
      globalDialog := TOpenDialog.Create(nil);
      try
        globalDialog.Filter := '*.txt';
        if globalDialog.Execute then
          Result := globalDialog.FileName
        else
          Result := '';
      finally
        FreeAndNil(globalDialog);
      end;
    end;
  end;

  function NumInputs: byte;
  begin
    Result := Inputs; // trasferire quantita entrata
  end;

  function NumOutputs: byte;
  begin
    Result := Outputs; // trasferire quantita uscita
  end;

  function InputName(Channel: byte): ShortString; // trasferire nome di entrata
  begin
    case Channel of
      I0: Result := 'I0'; // nome di pin I0
      I1: Result := 'I1'; // nome di pin I1
    end;
  end;

  function OutputName(Channel: byte): ShortString; // trasferire nome di uscita
  begin
    case Channel of
      Q0: Result := 'Q0'; // nome di pin Q0
      Q1: Result := 'Q1'; // nome di pin Q1
    end;
  end;


  procedure SimStart(PInput, POutput, PUser: PDLLParams); // Routine viene eseguita solo al primo avvio
  begin
    POutput^[Q0] := 0;
    POutput^[Q1] := 0;
  end;


  procedure Calculate(PInput, POutput, PUser: PDLLParams); // Routine è permanente
  begin
    if PInput^[I0] > 2.5 then
    begin
      ApriOpenDialog;
      POutput^[Q0] := 5;
    end;
    if PInput^[I1] > 2.5 then
    begin
      ApriSaveDialog;
      POutput^[Q1] := 5;
    end;
  end;

  procedure SimStop(PInput, POutput, PUser: PDLLParams); // Routine viene es                                                            eguita solo in fase di chiusura
  begin
    POutput^[Q0] := 0;
    POutput^[Q1] := 0;
  end;


  //export methods for ProfiLab
exports SimStart,
  SimStop,
  NumInputs,
  NumOutputs,
  Calculate,
  InputName,
  OutputName,
  ApriOpenDialog,
  ApriSaveDialog;
begin
end.
Titolo: Re:DLL con SaveDialog
Inserito da: Stilgar - Dicembre 31, 2012, 12:49:24 am
Occhio che adesso anche Legolas ti controlla il codice ;)
Titolo: Re:DLL con SaveDialog
Inserito da: Simon75 - Dicembre 31, 2012, 01:08:13 am
Allora è come prima, quando clicco sul bottone della opendialog si apre la finestra e il led è ancora spento quando la chiudo si accende...
Ormai state diventando Profilab dipendenti :)
Titolo: Re:DLL con SaveDialog
Inserito da: Stilgar - Dicembre 31, 2012, 01:16:33 am
Questo perchè non c'è nulla che leghi il bottone/led alla dialog del file.
Sono operazioni disgiunte.
Titolo: Re:DLL con SaveDialog
Inserito da: Stilgar - Dicembre 31, 2012, 01:18:27 am
Per legare le due cose si potrebbe fare in questo modo:
Codice: [Seleziona]

library dialog;

{$mode objfpc}{$H+}

uses
  Interfaces,
  Classes,
  SysUtils,
  Windows,
  FileUtil,
  Forms,
  Controls,
  Graphics,
  Dialogs;

const
  Inputs = 2;  // quantita entrata
  Outputs = 2; // quantita uscita

  {INPUTS}// nome per numero di entrata
  I0 = 0;  // valore I0 = PInput[I0] ossia PInput[0]
  I1 = 1;  // valore I1 = PInput[I1] ossia PInput[1]

  // I3 = 3;
  // ... I99 = 99;

  {OUTPUTS}// nome per numero di uscita
  Q0 = 0;  // valore Q0 = POutput[Q0] ossia POutput[0]
  Q1 = 1;  // valore Q1 = POutput[Q1] ossia POutput[1]

  // Q3 = 3;
  // ... Q99 = 99;

  {USER}// nome per numero di variabile, I valori vengono memorizzati

  U0 = 0; // valore U0 = PUser[U0] ossia PUser[0]
  // U1 = 1;
  // U2 = 2;
  // U3 = 3;
  // ... U99 = 99;

  // I0,I1,I2,I3,Q0,Q1,Q2,Q3,U0,U1,U2,U3
  // I nomi possono essere qualsiasi, sono case-insensitive
var
  globalDialog: TFileDialog;

type
  TDLLParams = array[0..100] of extended; //Type of ProfiLab DLL parameters
  PDLLParams = ^TDLLParams;               // Pointer to ProfiLab DLL parameters



  function ApriSaveDialog: ShortString;
  begin
    result := '';
    if not assigned(globalDialog) then
    begin
      globalDialog := TSaveDialog.Create(nil);
      try
        globalDialog.Filter := '*.txt';
        if globalDialog.Execute then
          Result := globalDialog.FileName
        else
          Result := '';
      finally
        FreeAndNil(globalDialog);
      end;
    end;
  end;

  function ApriOpenDialog: ShortString;
  begin
    result := '';
    if not assigned(globalDialog) then
    begin
      globalDialog := TOpenDialog.Create(nil);
      try
        globalDialog.Filter := '*.txt';
        if globalDialog.Execute then
          Result := globalDialog.FileName
        else
          Result := '';
      finally
        FreeAndNil(globalDialog);
      end;
    end;
  end;

  function NumInputs: byte;
  begin
    Result := Inputs; // trasferire quantita entrata
  end;

  function NumOutputs: byte;
  begin
    Result := Outputs; // trasferire quantita uscita
  end;

  function InputName(Channel: byte): ShortString; // trasferire nome di entrata
  begin
    case Channel of
      I0: Result := 'I0'; // nome di pin I0
      I1: Result := 'I1'; // nome di pin I1
    end;
  end;

  function OutputName(Channel: byte): ShortString; // trasferire nome di uscita
  begin
    case Channel of
      Q0: Result := 'Q0'; // nome di pin Q0
      Q1: Result := 'Q1'; // nome di pin Q1
    end;
  end;


  procedure SimStart(PInput, POutput, PUser: PDLLParams); // Routine viene eseguita solo al primo avvio
  begin
    POutput^[Q0] := 0;
    POutput^[Q1] := 0;
  end;


  procedure Calculate(PInput, POutput, PUser: PDLLParams); // Routine è permanente
  begin
    if PInput^[I0] > 2.5 then
    begin
      if ('' <> ApriOpenDialog) then
      POutput^[Q0] := 5
    else
      POutput^[Q0] := 0;
    end;
    if PInput^[I1] > 2.5 then
    begin
      if ('' <> ApriSaveDialog) then
        POutput^[Q1] := 5
      else
        POutput^[Q1] := 0;
    end;
  end;

  procedure SimStop(PInput, POutput, PUser: PDLLParams); // Routine viene es                                                            eguita solo in fase di chiusura
  begin
    POutput^[Q0] := 0;
    POutput^[Q1] := 0;
  end;


  //export methods for ProfiLab
exports SimStart,
  SimStop,
  NumInputs,
  NumOutputs,
  Calculate,
  InputName,
  OutputName,
  ApriOpenDialog,
  ApriSaveDialog;
begin
end.
Titolo: Re:DLL con SaveDialog
Inserito da: Simon75 - Dicembre 31, 2012, 01:26:51 am
Non si accendono ne quando apro e  ne quando chiudo  :)
Titolo: Re:DLL con SaveDialog
Inserito da: Stilgar - Dicembre 31, 2012, 01:30:20 am
Riavvi profilab dopo aver ricompilato la DLL?
Vero?
Titolo: Re:DLL con SaveDialog
Inserito da: Simon75 - Dicembre 31, 2012, 01:32:38 am
Certo sono obbligato a farlo altrimenti Lazarus non mi crea la nuova DLL.

Servono a questo le procedure che hai usato

Delphi: Procedure SimStart(PInput,POutput,PUser: PDLLParams);

This procedure is called once, when the ProfiLab project enters the RUN mode, and can be used to initialize DLL variables, etc. The parameters have been explained before.
 
Delphi: Procedure SimStop(PInput,POutput,PUser: PDLLParams);

This procedure is called once, when RUN mode is terminated, and can be used to close open files, etc. The parameters have been explained before.
Titolo: Re:DLL con SaveDialog
Inserito da: Stilgar - Dicembre 31, 2012, 01:36:40 am
Ok, allora prova a commentare l'azzeramento delle POutput dentro le SimStop ... fose a quel punto dovrebbe tenerti il vecchio valore ...(0 o 5)
Titolo: Re:DLL con SaveDialog
Inserito da: Simon75 - Dicembre 31, 2012, 02:10:40 am
Non si accendono i led
Titolo: Re:DLL con SaveDialog
Inserito da: Stilgar - Dicembre 31, 2012, 02:12:45 am
Ok, allora ProfiLab non l'ho installato sul PC, dovrò provvedere se Legolas non risolve la cosa dei Led.
Titolo: Re:DLL con SaveDialog
Inserito da: Legolas - Dicembre 31, 2012, 10:59:30 am
Mi servirebbe anche un progettino in ProfiLab per utilizzare la dll. Di elettronica non so una beata...  ;D

Edit: niente, me ne sono fatto uno basandomi su uno screenshot nelle pagine precedenti con due pb, il controller per la dll e due led   :)

Ho dato una letta alla documentazione di ProfiLab, in particolare sulla creazione di dll. Da quello che ho potuto capire, quello che vuoi fare sembrerebbe avere poco senso. Mi spiego: stai cercando di mischiare componenti hardware (led, bottoni) e componenti software (opendialog, savedialog) direttamente. Se questo è fattibile, a livello teorico, nel software di simulazione, non è detto che lo sia nella realtà. Inoltre nella documentazione c'è scritto chiaramente che la procedura "Calculate" è la principale della dll e viene chiamata in continuazione, quindi dovrebbe contenere solo ed esclusivamente il codice di calcolo. Eventuali configurazioni (e la scelta di un file di testo potrebbe rientrare nella casistica, dovrebbe essere inserita nella finestra di configurazione (nella procedura "Configure"), e non nel form di esecuzione della pcb simulata.


Invece, a livello teorico, il problema dei led che non si accendono è dovuto al fatto che, una volta cliccato sul button, il focus passa direttamente al dialog e, probabilmente, il codice per l'accensione del led non viene eseguito. Potrebbero servire degli eventi sul button (onPress e onRelease), che però non ci sono.  :(
Titolo: Re:DLL con SaveDialog
Inserito da: Simon75 - Gennaio 01, 2013, 12:01:16 am
Ciao Legolas ti ringrazio, per i led lascio perdere per il momento poiché era solo una opzione in più che volevo inserire..
Chiudo il topic poichè la domanda all'oggetto è stata risolta.
Apro per un altro topic per il secondo problema sempre inerente a questa DLL.
Ringrazio tutti