* * * *

Privacy Policy

Blog italiano

Clicca qui se vuoi andare al blog italiano su Lazarus e il pascal.

Forum ufficiale

Se non siete riusciti a reperire l'informazione che cercavate nei nostri articoli o sul nostro forum vi consiglio di visitare il
Forum ufficiale di Lazarus in lingua inglese.

Lazarus 1.0

Trascinare un file nel programma
DB concetti fondamentali e ZeosLib
Recuperare codice HTML da pagina web
Mandare mail con Lazarus
Stabilire il sistema operativo
Esempio lista in pascal
File INI
Codice di attivazione
Realizzare programmi multilingua
Lavorare con le directory
Utilizzare Unità esterne
TTreeView
TTreeview e Menu
Generare controlli RUN-TIME
LazReport, PDF ed immagini
Intercettare tasti premuti
Ampliare Lazarus
Lazarus e la crittografia
System Tray con Lazarus
UIB: Unified Interbase
Il file: questo sconosciuto
Conferma di chiusura di un applicazione
Liste e puntatori
Overload di funzioni
Funzioni a parametri variabili
Proprietà
Conversione numerica
TImage su Form e Panel
Indy gestiore server FTP lato Client
PopUpMenu sotto Pulsante (TSpeedButton)
Direttiva $macro
Toolbar
Evidenziare voci TreeView
Visualizzare un file Html esterno
StatusBar - aggirare l'errore variabile duplicata
Da DataSource a Excel
Le permutazioni
Brute force
Indy 10 - Invio email con allegati
La gestione degli errori in Lazarus
Pascal Script
Linux + Zeos + Firebird
Dataset virtuale
Overload di operatori
Lavorare con file in formato JSON con Lazarus
Zeos ... dietro le quinte (prima parte)
Disporre le finestre in un blocco unico (come Delphi)
Aspetto retrò (Cmd Line)
Lazarus 1.0
Come interfacciare periferica twain
Ubuntu - aggiornare free pascal e lazarus
fpcup: installazioni parallele di lazarus e fpc
Free Pascal e Lazarus sul Raspberry Pi
Cifratura: breve guida all'uso dell'algoritmo BlowFish con lazarus e free pascal.
Creare un server multithread
guida all'installazione di fpc trunk da subversion in linux gentoo
Indice
DB concetti fondamentali e connessioni standard
Advanced Record Syntax
DB concetti fondamentali e DBGrid
DB concetti fondamentali e TDBEdit, TDBMemo e TDBText
Advanced Record Syntax: un esempio pratico
Superclasse form base per programmi gestionali (e non)
Superclasse form base per programmi gestionali (e non) #2 - log, exception call stack, application toolbox
Superclasse form base per programmi gestionali (e non) #3 - traduzione delle form
Superclasse form base per programmi gestionali (e non) #4 - wait animation
Un dialog per la connessione al database:TfmSimpleDbConnectionDialog
Installare lazarus su mac osx sierra
immagine docker per lavorare con lazarus e free pascal
TDD o Test-Driven Development
Benvenuto! Effettua l'accesso oppure registrati.
Novembre 24, 2024, 07:09:16 am

Inserisci il nome utente, la password e la durata della sessione.

64 Visitatori, 0 Utenti

Autore Topic: DLL con SaveDialog  (Letto 41586 volte)

Simon75

  • Full Member
  • ***
  • Post: 139
  • Karma: +0/-0
DLL con SaveDialog
« il: 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:
« Ultima modifica: Dicembre 19, 2012, 09:48:17 am da Simon75 »
A volte bisogna commettere errori per capire qual è la cosa giusta da fare...

Const
Errori=Esperienza

nomorelogic

  • Global Moderator
  • Hero Member
  • *****
  • Post: 2921
  • Karma: +20/-4
Re:DLL con SaveDialog
« Risposta #1 il: 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
Imagination is more important than knowledge (A.Einstein)

Simon75

  • Full Member
  • ***
  • Post: 139
  • Karma: +0/-0
Re:DLL con SaveDialog
« Risposta #2 il: 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.
A volte bisogna commettere errori per capire qual è la cosa giusta da fare...

Const
Errori=Esperienza

nomorelogic

  • Global Moderator
  • Hero Member
  • *****
  • Post: 2921
  • Karma: +20/-4
Re:DLL con SaveDialog
« Risposta #3 il: 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
Imagination is more important than knowledge (A.Einstein)

Simon75

  • Full Member
  • ***
  • Post: 139
  • Karma: +0/-0
Re:DLL con SaveDialog
« Risposta #4 il: 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. 

A volte bisogna commettere errori per capire qual è la cosa giusta da fare...

Const
Errori=Esperienza

nomorelogic

  • Global Moderator
  • Hero Member
  • *****
  • Post: 2921
  • Karma: +20/-4
Re:DLL con SaveDialog
« Risposta #5 il: 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:
  • ApriOpenDialog non ritorna alcun valore in quanto è una procedura
  • ApriOpenDialog ha un parametro che non gli stai passando nella chiamata

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;
Imagination is more important than knowledge (A.Einstein)

Simon75

  • Full Member
  • ***
  • Post: 139
  • Karma: +0/-0
Re:DLL con SaveDialog
« Risposta #6 il: 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.
         

A volte bisogna commettere errori per capire qual è la cosa giusta da fare...

Const
Errori=Esperienza

Stilgar

  • Global Moderator
  • Hero Member
  • *****
  • Post: 2389
  • Karma: +10/-0
Re:DLL con SaveDialog
« Risposta #7 il: 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
« Ultima modifica: Dicembre 20, 2012, 04:16:36 pm da Stilgar »
Al mondo ci sono 10 tipi di persone ... chi capisce il binario e chi no.

Simon75

  • Full Member
  • ***
  • Post: 139
  • Karma: +0/-0
Re:DLL con SaveDialog
« Risposta #8 il: 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 ; 
« Ultima modifica: Dicembre 20, 2012, 04:21:21 pm da Simon75 »
A volte bisogna commettere errori per capire qual è la cosa giusta da fare...

Const
Errori=Esperienza

Stilgar

  • Global Moderator
  • Hero Member
  • *****
  • Post: 2389
  • Karma: +10/-0
Re:DLL con SaveDialog
« Risposta #9 il: 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
Al mondo ci sono 10 tipi di persone ... chi capisce il binario e chi no.

Simon75

  • Full Member
  • ***
  • Post: 139
  • Karma: +0/-0
Re:DLL con SaveDialog
« Risposta #10 il: 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


A volte bisogna commettere errori per capire qual è la cosa giusta da fare...

Const
Errori=Esperienza

Stilgar

  • Global Moderator
  • Hero Member
  • *****
  • Post: 2389
  • Karma: +10/-0
Re:DLL con SaveDialog
« Risposta #11 il: 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



Al mondo ci sono 10 tipi di persone ... chi capisce il binario e chi no.

Simon75

  • Full Member
  • ***
  • Post: 139
  • Karma: +0/-0
Re:DLL con SaveDialog
« Risposta #12 il: 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:



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. 
« Ultima modifica: Dicembre 21, 2012, 10:08:43 am da Simon75 »
A volte bisogna commettere errori per capire qual è la cosa giusta da fare...

Const
Errori=Esperienza

Simon75

  • Full Member
  • ***
  • Post: 139
  • Karma: +0/-0
Re:DLL con SaveDialog
« Risposta #13 il: 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.

A volte bisogna commettere errori per capire qual è la cosa giusta da fare...

Const
Errori=Esperienza

Stilgar

  • Global Moderator
  • Hero Member
  • *****
  • Post: 2389
  • Karma: +10/-0
Re:DLL con SaveDialog
« Risposta #14 il: 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
Al mondo ci sono 10 tipi di persone ... chi capisce il binario e chi no.

 

Recenti

How To

Utenti
  • Utenti in totale: 803
  • Latest: maXim.FI
Stats
  • Post in totale: 19180
  • Topic in totale: 2288
  • Online Today: 97
  • Online Ever: 900
  • (Gennaio 21, 2020, 08:17:49 pm)
Utenti Online
Users: 0
Guests: 64
Total: 64

Disclaimer:

Questo blog non rappresenta una testata giornalistica poiché viene aggiornato senza alcuna periodicità. Non può pertanto considerarsi un prodotto editoriale ai sensi della legge n. 62/2001.