Salve Signori :) quello che devo fare è dire alla SaveDialog di salvare quello che scrivo dentro le caselle nere e poi dire a OpenDialog di caricare il file di testo salvato con SaveDialog.
Non fate caso a ADD e PART loro fanno il loro lavoro poichè ADD mi genera la stringa creata da me nelle caselle nere ovvero le aggiunge e PART le divide in poche parole ho bisogno di un terzo ingresso che mi legga la riga di testo che esce da ADD $ e penso di usare un semplice read per tale scopo e un uscita con write che andra sull'ingresso $ di PART.
Posso usare assieme:
type TDLLParams = array[0..100] of extended;
PDLLParams = ^TDLLParams;
type TStringParams = array[0..100] of PChar;
PStringParams = ^TStringParams;
Anche perché dice questo:
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.
Procedure CalculateEx(PInput,POutput,PUser: PDLLParams; PStrings: PStringParams);
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.
Ringrazio
library dialog;
{$mode objfpc}{$H+}
uses
Interfaces,
Classes,
SysUtils,
Windows,
FileUtil,
Forms,
Controls,
Graphics,
Dialogs;
const
Inputs = 3; // quantita entrata
Outputs = 1; // 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]
$read = 2;
// I3 = 3;
// ... I99 = 99;
{OUTPUTS}// nome per numero di uscita
$write = 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
TStringParams = array[0..100] of PChar;
PStringParams = ^TStringParams;
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
$read: Result:='$read';
end;
end;
function OutputName(Channel: byte): ShortString; // trasferire nome di uscita
begin
case Channel of
$write: Result := '$write'; // 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
end;
procedure Calculate(PInput, POutput, PUser: PDLLParams); // Routine è permanente
begin
if PInput^[I0] > 2.5 then
begin
if ('' <> ApriOpenDialog) then
end;
if PInput^[I1] > 2.5 then
begin
if ('' <> ApriSaveDialog) then
end;
end;
Procedure CalculateEx(PInput,POutput,PUser: PDLLParams; PStrings: PStringParams);
begin
PInput^[$read]:=read;
POutput^[$write]:=write;
end;
procedure SimStop(PInput, POutput, PUser: PDLLParams); // Routine viene eseguita solo in fase di chiusura
begin
end;
//export methods for ProfiLab
exports
SimStart,
SimStop,
NumInputs,
NumOutputs,
Calculate,
InputName,
OutputName,
ApriOpenDialog,
ApriSaveDialog;
begin
end.
Attualmente mi genera questo errore:
project1.lpr(24,3) Fatal: Syntax error, "BEGIN" expected but "ordinal const" found
(http://i47.tinypic.com/au79e8.png)
(http://i50.tinypic.com/x1ee6x.png)
$read = 2;
// I3 = 3;
// ... I99 = 99;
{OUTPUTS}// nome per numero di uscita
$write = 0; // valore Q0 = POutput[Q0] ossia POutput[0]
Ciao,
il problema è l'uso del carattere $ ...
Non è un carattere valido per gli identificatori.
Se lo usi davanti ai numeri ottieni che il compilatore non interpreta le cifre in decimale ma in esadecimale.
Il "#" viene usato per definire i caratteri via decimale o "#$" in esadecimale.
In altri linguaggi il $ viene utilizzato come carattere per gli identificatori. Non il pascal (non mi risulta nemmeno Java e C/C++ permettano di usarlo).
Ciao e buon anno
Stilgar
OK, ora in queste condizioni mi genera senza errori la DLL ma ora rimane il problema che devo dire a SaveDialog di salvare quello che scrivo nelle caselle nere e dire a OpenDialog di cercare il file salvato che mi serve da caricare nelle caselle grigie.
;)
library dialog;
{$mode objfpc}{$H+}
uses
Interfaces,
Classes,
SysUtils,
Windows,
FileUtil,
Forms,
Controls,
Graphics,
Dialogs;
const
Inputs = 3; // quantita entrata
Outputs = 1; // 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]
read = 2;
// I3 = 3;
// ... I99 = 99;
{OUTPUTS}// nome per numero di uscita
write = 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
TStringParams = array[0..100] of PChar;
PStringParams = ^TStringParams;
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
read: Result:='$read';
end;
end;
function OutputName(Channel: byte): ShortString; // trasferire nome di uscita
begin
case Channel of
write: Result := '$write'; // 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
end;
procedure Calculate(PInput, POutput, PUser: PDLLParams); // Routine è permanente
begin
if PInput^[I0] > 2.5 then
begin
if ('' <> ApriOpenDialog) then
end;
if PInput^[I1] > 2.5 then
begin
if ('' <> ApriSaveDialog) then
end;
end;
Procedure CalculateEx(PInput,POutput,PUser: PDLLParams; PStrings: PStringParams);
begin
PInput^[read]:=read;
POutput^[write]:=write;
end;
procedure SimStop(PInput, POutput, PUser: PDLLParams); // Routine viene eseguita solo in fase di chiusura
begin
end;
//export methods for ProfiLab
exports
SimStart,
SimStop,
NumInputs,
NumOutputs,
Calculate,
InputName,
OutputName,
ApriOpenDialog,
ApriSaveDialog;
begin
end.
if ApriSaveDialog.Execute then
PInput^[read].Lines.SaveToFile( ApriSaveDialog.Filename );
end;
if ApriOpenDialog.Execute then
POutput^[write].Lines.LoadToFile( ApriOpenDialog.Filename );
end;
Dovrebbe uscire cosi giusto?
E dovrei metterlo in Calculate
Mi genera questo Errori:
project1.lpr(120,22) Hint: Parameter "PInput" not used
project1.lpr(120,30) Hint: Parameter "POutput" not used
project1.lpr(120,39) Hint: Parameter "PUser" not used
project1.lpr(133,20) Error: Illegal qualifier
project1.lpr(134,19) Error: Illegal qualifier
project1.lpr(134,52) Error: Illegal qualifier
project1.lpr(137,19) Error: Illegal qualifier
project1.lpr(138,12) Error: Identifier not found "POutput"
project1.lpr(138,56) Error: Illegal qualifier
project1.lpr(139,5) Fatal: Syntax error, "." expected but ";" found
procedure Calculate(PInput, POutput, PUser: PDLLParams); // Routine è permanente
begin
if ApriSaveDialog.Execute then
PInput^[read].Lines.SaveToFile( ApriSaveDialog.Filename );
end;
begin
if ApriOpenDialog.Execute then
POutput^[write].Lines.LoadFromFile( ApriOpenDialog.Filename );
end;
if PInput^[I0] > 2.5 then
begin
if ('' <> ApriOpenDialog) then
end;
if PInput^[I1] > 2.5 then
begin
if ('' <> ApriSaveDialog) then
end;
end;
Procedure CalculateEx(PInput,POutput,PUser: PDLLParams; PStrings: PStringParams);
begin
PInput^[read]:=read;
POutput^[write]:=write;
end;
Avete qualche idea???
c'è un po' di confusione nei begin/end e soprattutto le identazioni lasciano a desiderare e diventa più difficile capire cosa volevi scrivere :)
ad esempio cambia l'inizio come sotto e poi dai una sistemata anche al resto ;)
procedure Calculate(PInput, POutput, PUser: PDLLParams); // Routine è permanente
begin
if ApriSaveDialog.Execute then
PInput^[read].Lines.SaveToFile( ApriSaveDialog.Filename );
if ApriOpenDialog.Execute then
POutput^[write].Lines.LoadFromFile( ApriOpenDialog.Filename );
Cosa cavolo sto sbagliando :o mi metto a piangere adesso :'( :)
project1.lpr(120,22) Hint: Parameter "PInput" not used
project1.lpr(120,30) Hint: Parameter "POutput" not used
project1.lpr(120,39) Hint: Parameter "PUser" not used
project1.lpr(127,29) Hint: Parameter "POutput" not used
project1.lpr(127,38) Hint: Parameter "PUser" not used
project1.lpr(147,25) Error: Illegal qualifier
project1.lpr(148,25) Error: Illegal qualifier
project1.lpr(148,58) Error: Illegal qualifier
project1.lpr(151,25) Error: Illegal qualifier
project1.lpr(152,27) Error: Illegal qualifier
project1.lpr(152,62) Error: Illegal qualifier
project1.lpr(182) Fatal: There were 6 errors compiling module, stopping
procedure Calculate(PInput, POutput, PUser: PDLLParams); // Routine è permanente
begin
if PInput^[I0] > 2.5 then
begin
if ('' <> ApriOpenDialog) then
end;
if PInput^[I1] > 2.5 then
begin
if ('' <> ApriSaveDialog) then
end;
end;
Procedure CalculateEx(PInput,POutput,PUser: PDLLParams; PStrings: PStringParams);
begin
if ApriSaveDialog.Execute then
PInput^[read].Lines.SaveToFile( ApriSaveDialog.Filename );
if ApriOpenDialog.Execute then
POutput^[write].Lines.LoadFromFile( ApriOpenDialog.Filename );
PInput^[read]:=read;
POutput^[write]:=write;
end;
credo che il compilatore non capisca i blocchi begin/end ed effettivamente non è che si capisce cosa vuol dire:
if PInput^[I0] > 2.5 then
begin
if ('' <> ApriOpenDialog) then // qua c'è un "then" seguito da un "end"
end;
if PInput^[I1] > 2.5 then
begin
if ('' <> ApriSaveDialog) then // stesso errore di sopra
end;
parti da questa versione sotto, quando compila senza errori, inserisci una istruzione alla volta. è il modo migliore per capire quando scrivi qualcosa di sbagliato ;)
procedure Calculate(PInput, POutput, PUser: PDLLParams); // Routine è permanente
begin
if PInput^[I0] > 2.5 then
begin
end;
end;
Procedure CalculateEx(PInput,POutput,PUser: PDLLParams; PStrings: PStringParams);
begin
if ApriSaveDialog.Execute then
PInput^[read].Lines.SaveToFile( ApriSaveDialog.Filename );
if ApriOpenDialog.Execute then
POutput^[write].Lines.LoadFromFile( ApriOpenDialog.Filename );
PInput^[read]:=read;
POutput^[write]:=write;
end;
Mi sto perdendo :-\
Perché non compila?
project1.lpr(121,22) Hint: Parameter "PInput" not used
project1.lpr(121,30) Hint: Parameter "POutput" not used
project1.lpr(121,39) Hint: Parameter "PUser" not used
project1.lpr(128,29) Hint: Parameter "POutput" not used
project1.lpr(128,38) Hint: Parameter "PUser" not used
project1.lpr(148,25) Error: Illegal qualifier
project1.lpr(149,25) Error: Illegal qualifier
project1.lpr(149,58) Error: Illegal qualifier
project1.lpr(152,25) Error: Illegal qualifier
project1.lpr(153,27) Error: Illegal qualifier
project1.lpr(153,62) Error: Illegal qualifier
project1.lpr(183) Fatal: There were 6 errors compiling module, stopping
procedure Calculate(PInput, POutput, PUser: PDLLParams); // Routine è permanente
begin
if PInput^[I0] > 2.5 then ApriOpenDialog;
if PInput^[I1] > 2.5 then ApriSaveDialog;
end;
Procedure CalculateEx(PInput,POutput,PUser: PDLLParams; PStrings: PStringParams);
begin
if ApriSaveDialog.Execute then
PInput^[read].Lines.SaveToFile( ApriSaveDialog.Filename );
if ApriOpenDialog.Execute then
POutput^[write].Lines.LoadFromFile( ApriOpenDialog.Filename );
PInput^[read]:=read;
POutput^[write]:=write;
end;
mi evidenzia questi:
if ApriSaveDialog.Execute then
PInput^[read].Lines.SaveToFile( ApriSaveDialog.Filename );
if ApriOpenDialog.Execute then
Ecco è leggermente peggiorato
project1.lpr(122,22) Hint: Parameter "PInput" not used
project1.lpr(122,30) Hint: Parameter "POutput" not used
project1.lpr(122,39) Hint: Parameter "PUser" not used
project1.lpr(129,31) Hint: Parameter "POutput" not used
project1.lpr(129,40) Hint: Parameter "PUser" not used
project1.lpr(150,23) Error: Illegal qualifier
project1.lpr(151,15) Warning: Local variable "Read" does not seem to be initialized
project1.lpr(151,19) Error: Incompatible types: got "AnsiString" expected "ShortInt"
project1.lpr(151,53) Error: Illegal qualifier
project1.lpr(151,62) Error: Illegal expression
project1.lpr(154,23) Error: Illegal qualifier
project1.lpr(155,16) Warning: Local variable "Write" does not seem to be initialized
project1.lpr(155,21) Error: Incompatible types: got "AnsiString" expected "ShortInt"
project1.lpr(155,57) Error: Illegal qualifier
project1.lpr(155,66) Error: Illegal expression
project1.lpr(158,17) Error: Incompatible types: got "AnsiString" expected "ShortInt"
project1.lpr(160,19) Error: Incompatible types: got "AnsiString" expected "ShortInt"
project1.lpr(197) Fatal: There were 10 errors compiling module, stopping
procedure CalculateEx(PInput, POutput, PUser: PDLLParams; PStrings: PStringParams);
var
Read: string;
Write: string;
begin
if ApriSaveDialog.Execute then
PInput^[Read].Lines.SaveToFile(ApriSaveDialog.Filename);
if ApriOpenDialog.Execute then
POutput^[Write].Lines.LoadFromFile(ApriOpenDialog.Filename);
PInput^[Read] := Read;
POutput^[Write] := Write;
end;
Questo è tutto il codice
library dialog;
{$mode objfpc}{$H+}
uses
Interfaces,
Classes,
SysUtils,
Windows,
FileUtil,
Forms,
Controls,
Graphics,
Dialogs;
const
Inputs = 3; // quantita entrata
Outputs = 1; // 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]
Read = 2;
// I3 = 3;
// ... I99 = 99;
{OUTPUTS}// nome per numero di uscita
Write = 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
TStringParams = array[0..100] of PChar; //Type of ProfiLab DLL parameters
PStringParams = ^TStringParams; // 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
Read: Result := '$read';
end;
end;
function OutputName(Channel: byte): ShortString; // trasferire nome di uscita
begin
case Channel of
Write: Result := '$write'; // 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
end;
procedure Calculate(PInput, POutput, PUser: PDLLParams); // Routine è permanente
begin
if PInput^[I0] > 2.5 then
ApriOpenDialog;
if PInput^[I1] > 2.5 then
ApriSaveDialog;
end;
procedure CalculateEx(PInput, POutput, PUser: PDLLParams; PStrings: PStringParams);
var
Read: string;
Write: string;
begin
if ApriSaveDialog.Execute then
PInput^[Read].Lines.SaveToFile(ApriSaveDialog.Filename);
if ApriOpenDialog.Execute then
POutput^[Write].Lines.LoadFromFile(ApriOpenDialog.Filename);
PInput^[Read] := Read;
POutput^[Write] := Write;
end;
procedure SimStop(PInput, POutput, PUser: PDLLParams);
// Routine viene eseguita solo in fase di chiusura
begin
end;
//export methods for ProfiLab
exports
SimStart,
SimStop,
NumInputs,
NumOutputs,
Calculate,
InputName,
OutputName,
ApriOpenDialog,
ApriSaveDialog;
begin
end.
Simon ... dai ammettilo... scrivi codice a caso per prenderci in giro ...
Prima dichiari le costanti come numeri, adesso come variabili stringa ;)
Per poi usarli come numeri :D
var
Read: string;
Write: string;
begin
if ApriSaveDialog.Execute then
PInput^[Read].Lines.SaveToFile(ApriSaveDialog.Filename);
Te lo dice anche il compilatore ;)
project1.lpr(151,15) Warning: Local variable "Read" does not seem to be initialized
project1.lpr(151,19) Error: Incompatible types: got "AnsiString" expected "ShortInt"
No, Simon non hai affatto bisogno di stringe ...
hai bisogno di numeri.
Stai andando ad usarli come indici di un array.
Gli array vogliono la posizione ...
Metti
Read :=0;
Write := 0;
PInput^[Read] := Read;
POutput^[Write] := Write;
Poi se vuoi fare altro ... questo non lo so, ma dal tuo codice ... ti servono "Word".
Salve a tutti, ma se devo acquisire stringhe e numeri dall'ingresso read e poi salvarle con savedialog non ho bisogno di variabili:string?
I puntatori cosi configurati non dovrebbero darmi problemi o sbaglio?
type
TDLLParams = array[0..100] of extended; //Type of ProfiLab DLL parameters
PDLLParams = ^TDLLParams; // Pointer to ProfiLab DLL parameters
TStringParams = array[0..100] of PChar; //Type of ProfiLab DLL parameters
PStringParams = ^TStringParams; // Pointer to ProfiLab DLL parameters
Voglio usare read per prendere il dato dall'utente ovvero caselle nere e acquisire con le caselle grigie i dati salvati con savedialog.
per salvare un array in una lista di stringhe dovresti fare qualcosa del genere:
var i:integer;
sl: TStringList;
begin
sl := TStringList.Create;
try
for i := low(PDLLParams^) to high(PDLLParams^) do
sl.Values[ inttostr(i) ] := FloatToStr( PDLLParams^[i] );
sl.SaveToFile(...);
finally
sl.Free;
end;
end;
tieni conto che l'ho scritto di getto e non ho provato neanche a compilare, si tratta di darti un'idea
il fatto simon è che dal codice che scrivi appare chiaro che non hai acquisito le basi del pascal: usare una stringa come indice di un array o sperare che un array di extended abbia una proprietà che espone una istanza di TStrings vuol dire che probabilmente non è il momento di iniziare a scrivere codice complesso come quello che vuoi fare tu.
dovresti seguire il consiglio di legolas e stilgar e cioè apprendere le basi del pascal, IMHO le letture che ti ha consigilato legolas vanno più che bene ;)
Allora il problema sonoo solo queste righe, ho provato a commentarle e tutto ha funzionato ho tolto il commento e mi ha generato l'errore.
Se ruscite a darmi una mano su queste righe sono a cavallo ;)
Vi ringrazio
if ApriSaveDialog.Execute then
PInput^[Read].Lines.SaveToFile(ApriSaveDialog.Filename);
if ApriOpenDialog.Execute then
POutput^[Write].Lines.LoadFromFile(ApriOpenDialog.Filename);
Inserisco tutto il codice:
library dialog;
{$mode objfpc}{$H+}
uses
Interfaces,
Classes,
SysUtils,
Windows,
FileUtil,
Forms,
Controls,
Graphics,
Dialogs;
const
Inputs = 3; // quantita entrata
Outputs = 1; // 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]
Read = 2;
// I3 = 3;
// ... I99 = 99;
{OUTPUTS}// nome per numero di uscita
Write = 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
TStringParams = array[0..100] of PChar; //Type of ProfiLab DLL parameters
PStringParams = ^TStringParams; // 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
Read: Result := '$read';
end;
end;
function OutputName(Channel: byte): ShortString; // trasferire nome di uscita
begin
case Channel of
Write: Result := '$write'; // 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
end;
Procedure CalculateEx(PInput,POutput,PUser: PDLLParams; PStrings: PStringParams); // Routine è permanente
begin
if PInput^[I0] > 2.5 then
ApriOpenDialog;
if PInput^[I1] > 2.5 then
ApriSaveDialog;
PInput^[Read] := Read;
POutput^[Write] := Write ;
if ApriSaveDialog.Execute then
PInput^[Read];Lines.SaveToFile(ApriSaveDialog.Filename);
if ApriOpenDialog.Execute then
POutput^[Write];Lines.LoadFromFile(ApriOpenDialog.Filename);
end;
procedure SimStop(PInput, POutput, PUser: PDLLParams);
// Routine viene eseguita solo in fase di chiusura
begin
end;
//export methods for ProfiLab
exports
SimStart,
SimStop,
NumInputs,
NumOutputs,
CalculateEx,
InputName,
OutputName,
ApriOpenDialog,
ApriSaveDialog;
begin
end.
farei così:
da qualche parte dichiara:
procedure SalvaArrayInFile(FileName: string);
var i:integer;
sl: TStringList;
begin
sl := TStringList.Create;
try
for i := low(PDLLParams^) to high(PDLLParams^) do
sl.Values[ inttostr(i) ] := FloatToStr( PDLLParams^[i] );
sl.SaveToFile(FileName);
finally
sl.Free;
end;
end;
poi:
if ApriSaveDialog.Execute then
PInput^[Read];Lines.SaveToFile(ApriSaveDialog.Filename);
dovrebbe diventare:
if ApriSaveDialog.Execute then
SalvaArrayInFile(ApriSaveDialog.Filename);
poi dovresti fare qualcosa di simile per il load
Ciao nomorelogic
ecco gli errori che mi da adesso
project1.lpr(122,22) Hint: Parameter "PInput" not used
project1.lpr(122,30) Hint: Parameter "POutput" not used
project1.lpr(122,39) Hint: Parameter "PUser" not used
project1.lpr(136,46) Error: type identifier not allowed here
project1.lpr(166,23) Error: Illegal qualifier
project1.lpr(167,39) Error: Illegal qualifier
project1.lpr(222) Fatal: There were 3 errors compiling module, stopping
Le linea che mi da errore è questa:
sl.Values[IntToStr(i)] := FloatToStr(PDLLParams^[i]);
Poi queste:
if ApriSaveDialog.Execute then
SalvaArrayInFile(ApriSaveDialog.Filename)
questa viene compilata e puoi testarla
library lib01;
{$mode objfpc}{$H+}
uses
Interfaces,
Classes,
SysUtils,
Windows,
FileUtil,
Forms,
Controls,
Graphics,
Dialogs;
const
Inputs = 3; // quantita entrata
Outputs = 1; // 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]
Read = 2;
// I3 = 3;
// ... I99 = 99;
{OUTPUTS}// nome per numero di uscita
Write = 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
TStringParams = array[0..100] of PChar; //Type of ProfiLab DLL parameters
PStringParams = ^TStringParams; // 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
Read: Result := '$read';
end;
end;
function OutputName(Channel: byte): ShortString; // trasferire nome di uscita
begin
case Channel of
Write: Result := '$write'; // 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
end;
procedure SalvaArrayInFile(FileName: string; PAParams: PDLLParams);
var i:integer;
sl: TStringList;
begin
sl := TStringList.Create;
try
for i := low(PAParams^) to high(PAParams^) do
sl.Values[ inttostr(i) ] := FloatToStr( PAParams^[i] );
sl.SaveToFile(FileName);
finally
sl.Free;
end;
end;
procedure CaricaArrayDaFile(FileName: string; PAParams: PDLLParams);
var i:integer;
sl: TStringList;
e: extended;
s: string;
begin
sl := TStringList.Create;
try
sl.LoadFromFile(FileName);
for i := low(PAParams^) to high(PAParams^) do
begin
// piuttosto che scrivere:
// PAParams^[i] := StrToFloat(sl.Values[ inttostr(i) ]);
// scrivendo come sotto è più facile fare il debug
// quando l'hai testata puoi usare la forma commentata qui sopra
s := sl.Values[ inttostr(i) ];
e := StrToFloat(s);
PAParams^[i] := e
end;
finally
sl.Free;
end;
end;
Procedure CalculateEx(PInput,POutput,PUser: PDLLParams; PStrings: PStringParams); // Routine è permanente
var s: shortstring;
begin
if PInput^[I0] > 2.5 then
ApriOpenDialog;
if PInput^[I1] > 2.5 then
ApriSaveDialog;
PInput^[Read] := Read;
POutput^[Write] := Write ;
s := ApriSaveDialog;
if s <> '' then
SalvaArrayInFile(s, POutput);
s := ApriOpenDialog;
if s <> '' then
CaricaArrayDaFile(s, POutput);
end;
procedure SimStop(PInput, POutput, PUser: PDLLParams);
// Routine viene eseguita solo in fase di chiusura
begin
end;
//export methods for ProfiLab
exports
SimStart,
SimStop,
NumInputs,
NumOutputs,
CalculateEx,
InputName,
OutputName,
ApriOpenDialog,
ApriSaveDialog;
begin
end.
Ciao nomore ti ringrazio molto, attualmente appena provo a mandare in esecuzione il programma(Profilab) le OpenDialog e SaveDialog si aprono da sole senza premere i pulsanti.
Ho aggiunto 2 variabili che mi serviranno per leggere e scrivere ma generano questo errore:
procedure CalculateEx(PInput, POutput, PUser: PDLLParams; PStrings: PStringParams);
// Routine è permanente
var
s: shortstring;
lettura:string; // ho aggiunto queste variabili poichè mi serve leggere
scrittura:string; // ho aggiunto queste variabili poichè mi serve srivere
begin
if PInput^[I0] > 2.5 then
ApriOpenDialog;
if PInput^[I1] > 2.5 then
ApriSaveDialog;
PInput^[Leggi] := read(lettura); //le due variabili le ho messe qui
POutput^[Stampa] := write(scrittura); //le due variabili le ho messe qui
s := ApriSaveDialog;
if s <> '' then
SalvaArrayInFile(s, POutput);
s := ApriOpenDialog;
if s <> '' then
CaricaArrayDaFile(s, POutput);
end;
project1.lpr(122,22) Hint: Parameter "PInput" not used
project1.lpr(122,30) Hint: Parameter "POutput" not used
project1.lpr(122,39) Hint: Parameter "PUser" not used
project1.lpr(182,36) Error: Incompatible types: got "untyped" expected "Extended"
project1.lpr(183,40) Warning: Local variable "scrittura" does not seem to be initialized
project1.lpr(183,41) Error: Incompatible types: got "untyped" expected "Extended"
project1.lpr(218) Fatal: There were 2 errors compiling module, stopping
Ecco la dll completa:
library lib01;
{$mode objfpc}{$H+}
uses
Interfaces,
Classes,
SysUtils,
Windows,
FileUtil,
Forms,
Controls,
Graphics,
Dialogs;
const
Inputs = 3; // quantita entrata
Outputs = 1; // 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]
Leggi = 2;
// I3 = 3;
// ... I99 = 99;
{OUTPUTS}// nome per numero di uscita
Stampa = 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
TStringParams = array[0..100] of PChar; //Type of ProfiLab DLL parameters
PStringParams = ^TStringParams; // 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
Leggi: Result := '$Leggi';
end;
end;
function OutputName(Channel: byte): ShortString; // trasferire nome di uscita
begin
case Channel of
Stampa: Result := '$Stampa'; // 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
end;
procedure SalvaArrayInFile(FileName: string; PAParams: PDLLParams);
var
i: integer;
sl: TStringList;
begin
sl := TStringList.Create;
try
for i := low(PAParams^) to high(PAParams^) do
sl.Values[IntToStr(i)] := FloatToStr(PAParams^[i]);
sl.SaveToFile(FileName);
finally
sl.Free;
end;
end;
procedure CaricaArrayDaFile(FileName: string; PAParams: PDLLParams);
var
i: integer;
sl: TStringList;
e: extended;
s: string;
begin
sl := TStringList.Create;
try
sl.LoadFromFile(FileName);
for i := low(PAParams^) to high(PAParams^) do
begin
// piuttosto che scrivere:
// PAParams^[i] := StrToFloat(sl.Values[ inttostr(i) ]);
// scrivendo come sotto è più facile fare il debug
// quando l'hai testata puoi usare la forma commentata qui sopra
s := sl.Values[IntToStr(i)];
e := StrToFloat(s);
PAParams^[i] := e;
end;
finally
sl.Free;
end;
end;
procedure CalculateEx(PInput, POutput, PUser: PDLLParams; PStrings: PStringParams);
// Routine è permanente
var
s: shortstring;
lettura:string; // ho aggiunto queste variabili poichè mi serve leggere
scrittura:string; // ho aggiunto queste variabili poichè mi serve srivere
begin
if PInput^[I0] > 2.5 then
ApriOpenDialog;
if PInput^[I1] > 2.5 then
ApriSaveDialog;
PInput^[Leggi] := read(lettura); //le due variabili le ho messe qui
POutput^[Stampa] := write(scrittura); //le due variabili le ho messe qui
s := ApriSaveDialog;
if s <> '' then
SalvaArrayInFile(s, POutput);
s := ApriOpenDialog;
if s <> '' then
CaricaArrayDaFile(s, POutput);
end;
procedure SimStop(PInput, POutput, PUser: PDLLParams);
// Routine viene eseguita solo in fase di chiusura
begin
end;
//export methods for ProfiLab
exports
SimStart,
SimStop,
NumInputs,
NumOutputs,
CalculateEx,
InputName,
OutputName,
ApriOpenDialog,
ApriSaveDialog;
begin
end.
Ringrazio per l'attenzione
Purtroppo continui a ignorare i suggerimenti che ti vengono dati e ad aggiungere comandi a casaccio... :(
In questo modo, pur volendo, è davvero difficile poterti dare una mano, anche perché - e non è un rimprovero, ma una costatazione - parliamo linguaggi (di programmazione) differenti.
Ad esempio, ti avevo suggerito di aggiungere tutta la parte riguardante la configurazione nel comando Configure(), ma continui a metterla nel loop principale della dll.
Poi, spulciando tra i componenti di Profilab, ce ne sono alcuni che si occupano dell'input/output su file. Ho il sospetto che dovrai usare quelli per salvare e caricare valori. Ancora: c'è un componente che ti permette di salvare lo stato del front panel. Il componente Numeric Input accetta solo valori in uscita, quindi dalla dll non puoi impostarne il valore, ma soltanto utilizzando il componente di cui sopra.
Ciò detto, ho preparato un progettino di una semplice dll che accetta un input numerico e lo restituisce moltiplicato per un valore da impostare in una dialog di configurazione della dll. Vedi se riesci a tirarci fuori qualcosa di utile per il tuo progetto :)
Numeric Input --> DLL --> Numeric Display
Vi ringrazio per il supporto :)
Forse mi spiego male piccola parentesi per Legolas( ho bisogno di chiamare le OpenDialog e SaveDialog da dei bottoni non posso configurare e poi avviare l'applicazione, poi le numeric input sono uscite analogiche.Nel software non ce un modo per salvare su disco e poi richiamare il file salvato è per quello che mi sono ridotto a creare una DLL.
Quello che ho bisogno è di poter salvare su disco dei file txt tramite SaveDialog usando le numeric input, una volta salvate su disco devo poter richiamare il file txt con OpenDialog per poterlo caricare nelle numeric display ad ogni save con SaveDialog avrò tanti file txt dove poi potro scegliere cosa caricare con OpenDialog dentro le numeric display.
Ho inserito queste variabili appunto perché mi serve un modo per leggere nella variabile lettura quello che acquisisco da ADD e la variabile scrittura per stampare nelle numeric display quello che leggo da i file txt aprendoli con OpenDialog.
lettura: string; // ho aggiunto queste variabili poichè mi serve leggere
scrittura: string; // ho aggiunto queste variabili poichè mi serve srivere
PInput^[Leggi] := read(lettura); //le due variabili le ho messe qui
POutput^[Stampa] := write(scrittura); //le due variabili le ho messe qui
(http://i50.tinypic.com/2uptvo5.png)
Grazie per l'attenzione.
simon75
le difficoltà che ci sono nell'apprendere un nuovo linguaggio di programmazione sono il pane quotidiano di tutti noi che in un modo o nell'altro diamo una mano in questo forum.
Però devi capire che il codice che tu scrivi, 2 righe alla volta, è costantemente un nonsense. Condito con le tue idee per aiutarci a capire cosa vuoi realizzare, ma di nonsense si tratta e per portarlo a termine hai bisogno di qualcuno che mastichi pascal.
Sei stato corretto all'inizio a specificare che non sei un programmatore pascal ma, per lavorare in questo modo, dovresti prima chiedere nel forum se c'è qualcuno che vuole partecipare al tuo progetto. Questo forum serve anche a questo, anzi, serve a questo e con questo si arricchisce.
Questo post non vuole essere un rimprovero ovviamente.
Devi però comprendere che non puoi darci le direttive per scrivere il tuo progetto. :)
Esempio di nonsense :) :
PInput^[Leggi] := read(lettura);
Ciao Legolas, cosa serve questo?
{USER}
U0 = 0;
DLLIndex = 100;
Dove hai preso questa libreria?
Puoi spiegarmi questo pezzo di codice?
procedure Configure(PUser: PDLLParams);
var
DLG: TForm1;
begin
DLG := TForm1.Create(nil);
with DLG do
begin
Caption := 'Counter [DLL' + FloatToStr(PUser^[DLLIndex]) + ']';
if ShowModal = mrOk then
begin
puser^[U0] := SpinEdit1.Value;
end;
Free;
end;
end;
Quel bottone che hai messo per moltiplicare i numeri come hai fatto a richiamarlo ovvero a renderlo visibile?
Ciao
Ti ringrazio
Simon,
il progetto ha 2 "unità" logiche.
C'è il principale e una "form".
La form usa 2 file: "lfm" e "pas".
lfm contiene la definizioni e le risorse dei componenti grafici.
pas contiene il codice che usa il compilatore.
Il codice per il quale chiedevi spiegazioni è abbastanza semplice:
procedure Configure(PUser: PDLLParams);
var
DLG: TForm1; // <- Definizione di una variabile di tipo TForm1
begin
DLG := TForm1.Create(nil); // <- Creazione dell'istanza della classe
with DLG do // <- Serve a non ripettere di continuo DLG ad ogni utilzzo... come una sorta di scorciatoia
begin
Caption := 'Counter [DLL' + FloatToStr(PUser^[DLLIndex]) + ']'; //<- Assegna alla parte alta della finestra (caption) una stringa
if ShowModal = mrOk then // <- Fa diventare MODALE la form. Rimane in primo piano (sull'applicazione)
begin // <- Qui si entra solo se viene resituita OK dalla form di prima.
puser^[U0] := SpinEdit1.Value; // <- Assegna il valore del SpinEdit1 al PUser[U0].
end;
Free; Rilascia la ram dell'istanza usata
end;
end;
Grazie stilgar,
Per esempio potrei richimare qualsiasi oggetto? basta cambiare con TForm l'oggetto desiderato?
DLG: TForm1; // <- Definizione di una variabile di tipo TForm1
Ma che libreria prende questa?
Questa è una costante perché l'ha messa in user?
Cosa serve metterla in user?
Perché 100?
Cavolo non ho fatto caso della Unit1 nella cartella :)
Ha dovuto scriverla Legolas, oppure l'ha composta con gli oggetti gia pronti di Lazarus?
unit Unit1;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls,
Spin;
type
{ TForm1 }
TForm1 = class(TForm)
Button1: TButton;
Button2: TButton;
Button3: TButton;
Button4: TButton;
Edit1: TEdit;
Edit2: TEdit;
OpenDialog1: TOpenDialog;
SaveDialog1: TSaveDialog;
SpinEdit1: TSpinEdit;
procedure Button3Click(Sender: TObject);
procedure Button4Click(Sender: TObject);
private
{ private declarations }
public
{ public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.lfm}
{ TForm1 }
procedure TForm1.Button3Click(Sender: TObject);
begin
if OpenDialog1.Execute then
edit1.Text := OpenDialog1.FileName;
end;
procedure TForm1.Button4Click(Sender: TObject);
begin
if SaveDialog1.Execute then
edit2.Text := SaveDialog1.FileName;
end;
initialization
Application.Initialize;
end.
Saluti
Legolas, quindi in procedure Configure(PUser: PDLLParams);
hai richiamato la unit1 giusto?
Non potevi usare solo Unit1 invece di
Legolas, quindi in procedure Configure(PUser: PDLLParams);
hai richiamato la unit1 giusto?
Sì, esatto
Non potevi usare solo Unit1 invece di
In questo caso sì, le due chiamate sono equivalenti. Se invece volessi aggiungere alla dll una unit presente in un'altra cartella, con "in" potrei specificare il percorso corretto. Ad esempio, se muovo unit1.pas e unit1.lfm nella cartella "units_della_dll", allora dovrei per forza scrivere:
Unit1 in 'units_della_dll\Unit1.pas';
Ciao nomore ti ringrazio molto, attualmente appena provo a mandare in esecuzione il programma(Profilab) le OpenDialog e SaveDialog si aprono da sole senza premere i pulsanti.
In effetti avevo scritto una castroneria, prova così:
Procedure CalculateEx(PInput,POutput,PUser: PDLLParams; PStrings: PStringParams); // Routine è permanente
var s: shortstring;
begin
if PInput^[I0] > 2.5 then
begin
s := ApriOpenDialog;
if s <> '' then
CaricaArrayDaFile(s, POutput);
end;
if PInput^[I1] > 2.5 then
begin
s := ApriSaveDialog;
if s <> '' then
SalvaArrayInFile(s, POutput);
end;
PInput^[Read] := Read;
POutput^[Write] := Write ;
end;
In questo modo i dialog dovrebbero aprirsi solo a comando.
Dovrebbe funzionare sia il salvataggio che il caricamento, facci sapere.
Ciao
Writeln(Output,'Testo di prova');
equivale a
Writeln('Testo di prova');
Se esegui prima un :
AssignFile(Output,'Filedioutput.txt');
Rewrite(Output);
fai grosso modo quello che per la console viene fatto per "puntare" all'output a video. Solo che fai il tutto su file.
Stessa cosa per il read. Al posto di averlo aperto su input standard (tastiera) puoi far leggere da file.
Stilgar
Ma Read e Write come sono adesso cosa sono? non mi sembrano variabili e quindi non posso scriverci dentro è anche per quello che non mi legge e ne stampa.
procedure CalculateEx(PInput, POutput, PUser: PDLLParams; PStrings: PStringParams);
// Routine è permanente
var
s: shortstring;
begin
if PInput^[I0] > 2.5 then
begin
s := ApriOpenDialog;
if s <> '' then
CaricaArrayDaFile(s, POutput);
end;
if PInput^[I1] > 2.5 then
begin
s := ApriSaveDialog;
if s <> '' then
SalvaArrayInFile(s, POutput);
end;
PInput^[Read] := Read;
POutput^[Write] := Write;
end;
PInput^[Read] := Read; //Questo ingresso Read cosa legge?
POutput^[Write] := Write; //Questa uscita write cosa stampa?
const
Inputs = 3; // quantita entrata
Outputs = 1; // 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]
Read = 2;
// I3 = 3;
// ... I99 = 99;
{OUTPUTS}// nome per numero di uscita
Write = 0; // valore Q0 = POutput[Q0] ossia POutput[0]
//Q1 = 1; // valore Q1 = POutput[Q1] ossia POutput[1]
infatti sono costanti che valgono una Read = 2; Write = 0;
ecco perchè non funziona :o
Quindi dovrei dichiarare delle variabili per leggere e stampare ma le dichiaro come?
ho bisogno di leggere delle stringhe e stampare stringhe metterei
procedure CalculateEx......;
Var
Leggi : string;
Stampa : string;
begin
......
.......
.......
PInput^[Read] := read(Leggi) ;
POutput^[Write] := write(Stampa);
end;
Solo che mi darà problemi il compilatore e quindi dovrei convertirlo da stringa a extended potrei usare:
PInput^[Leggi] = StrToFloat(StringReplace(lettura,'.', ',',
[rfReplaceAll]));
Non so ditemi voi :)
Mi sa che ho bisogno di una controllatina ??? :)
function StrToFloat ( FloatString : string ) : Extended;
Var
Leggi: string;
Leggiuno:extended;
Stampa: string;
Stampauno:extended;
begin
Leggi:= PInput^[Read];
leggiuno:=Leggi StrToFloat(Leggi);
Stampa:=POutput^[Write];
Stampauno:=Stampa StrToFloat(Stampa);
end;
procedure CalculateEx............
.......
.......
......
......
.......
PInput^[Read] := readln(Leggi);
POutput^[Write] := writeln(Stampa);
end;
begin
Leggi:= PInput^[Read];
leggiuno:=Leggi StrToFloat(Leggi);
Stampa:=POutput^[Write];
Stampauno:=Stampa StrToFloat(Stampa);
end;
Osservazioni:
1) Ammesso che ti abbia compilato (e non credo), cosa volevi scrivere con
leggiuno:=Leggi StrToFloat(Leggi);
Togli "Leggi" dopo ":=". Forse ti compila.
2) Ammesso che volessi scrivere
function StrToFloat ( FloatString : string ) : Extended;
begin
...
leggiuno:=StrToFloat(Leggi);
Richiami la funzione dentro la funzione (ricosione) ma non vedo la condizione di uscita. Qui ti crepa lo stack di chiamata.
3) Leggi e scrivi... chi le valorizza?
Nessuno, per cui stai leggendo casualmente la memoria.
function StrToFloat ( FloatString : string ) : Extended;
Var
Leggi: string;
Leggiuno:extended;
Stampa: string;
Stampauno:extended;
begin
Leggi:= PInput^[Read];
Ma se usi una funzione che legge una stringa e la traduce in numero, perchè non ti è venuto in mente di una stringa e tradurla in numero?
Non siamo in javascript che tutto fa brodo. ;)
Stilgar
Non riesco a capire come restituire il valore con le funzioni:
es:
function StrToFloat(Leggi, Stampa: string): extended;
begin
StrToFloat := StrToFloat(Stampa);
StrToFloat := StrToFloat(Leggi);
end;
procedure CalculateEx......
var
Leggi: extended;
Stampa: extended;
begin
............
............
.........
..........
.........
PInput^[Read] := readln(StrToFloat);
POutput^[Write] := writeln(StrToFloat);
end;
Helppppppppppp :)
procedure CalculateEx(PInput, POutput, PUser: PDLLParams; PStrings: PStringParams);
// Routine è permanente
var
Leggi:string;
Stampa:string;
s: shortstring;
begin
if PInput^[I0] > 2.5 then
begin
s := ApriOpenDialog;
if s <> '' then
CaricaArrayDaFile(s, POutput);
end;
if PInput^[I1] > 2.5 then
begin
s := ApriSaveDialog;
if s <> '' then
SalvaArrayInFile(s, POutput);
end;
PInput^[Leggi] = StrToFloat(StringReplace(Leggi.Text,'.', ',',
[rfReplaceAll]));
POutput^[Stampa] = StrToFloat(StringReplace(Stampa.Text,'.', ',',
[rfReplaceAll]));
end;
project1.lpr(129,22) Hint: Parameter "PInput" not used
project1.lpr(129,30) Hint: Parameter "POutput" not used
project1.lpr(129,39) Hint: Parameter "PUser" not used
project1.lpr(204,13) Warning: Local variable "Leggi" does not seem to be initialized
project1.lpr(204,18) Error: Incompatible types: got "AnsiString" expected "ShortInt"
project1.lpr(204,53) Error: Illegal qualifier
project1.lpr(205,21) Error: Illegal expression
project1.lpr(206,15) Warning: Local variable "Stampa" does not seem to be initialized
project1.lpr(206,21) Error: Incompatible types: got "AnsiString" expected "ShortInt"
project1.lpr(206,57) Error: Illegal qualifier
project1.lpr(207,21) Error: Illegal expression
project1.lpr(236) Fatal: There were 6 errors compiling module, stopping
Tutta la DLL
library project1;
{$mode objfpc}{$H+}
uses
Interfaces,
Classes,
SysUtils,
Windows,
FileUtil,
Forms,
Controls,
Graphics,
Dialogs,
ShellApi;
const
Inputs = 3; // quantita entrata
Outputs = 1; // 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]
Leggi = 2;
// I3 = 3;
// ... I99 = 99;
{OUTPUTS}// nome per numero di uscita
Stampa = 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
TStringParams = array[0..100] of PChar; //Type of ProfiLab DLL parameters
PStringParams = ^TStringParams; // Pointer to ProfiLab DLL parameters
function ApriSaveDialog: ShortString;
begin
Result := '';
if not assigned(globalDialog) then
begin
globalDialog := TSaveDialog.Create(nil);
try
globalDialog.DefaultExt := 'txt';
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.DefaultExt := 'txt';
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
Leggi: Result := '$Leggi';
end;
end;
function OutputName(Channel: byte): ShortString; // trasferire nome di uscita
begin
case Channel of
Stampa: Result := '$Stampa'; // 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
end;
procedure SalvaArrayInFile(FileName: string; PAParams: PDLLParams);
var
i: integer;
sl: TStringList;
begin
sl := TStringList.Create;
try
for i := low(PAParams^) to high(PAParams^) do
sl.Values[IntToStr(i)] := FloatToStr(PAParams^[i]);
sl.SaveToFile(FileName);
finally
sl.Free;
end;
end;
procedure CaricaArrayDaFile(FileName: string; PAParams: PDLLParams);
var
i: integer;
sl: TStringList;
e: extended;
s: string;
begin
sl := TStringList.Create;
try
sl.LoadFromFile(FileName);
for i := low(PAParams^) to high(PAParams^) do
begin
// piuttosto che scrivere:
// PAParams^[i] := StrToFloat(sl.Values[ inttostr(i) ]);
// scrivendo come sotto è più facile fare il debug
// quando l'hai testata puoi usare la forma commentata qui sopra
s := sl.Values[IntToStr(i)];
e := StrToFloat(s);
PAParams^[i] := e;
end;
finally
sl.Free;
end;
end;
procedure CalculateEx(PInput, POutput, PUser: PDLLParams; PStrings: PStringParams);
// Routine è permanente
var
Leggi:string;
Stampa:string;
s: shortstring;
begin
if PInput^[I0] > 2.5 then
begin
s := ApriOpenDialog;
if s <> '' then
CaricaArrayDaFile(s, POutput);
end;
if PInput^[I1] > 2.5 then
begin
s := ApriSaveDialog;
if s <> '' then
SalvaArrayInFile(s, POutput);
end;
PInput^[Leggi] = StrToFloat(StringReplace(Leggi.Text,'.', ',',
[rfReplaceAll]));
POutput^[Stampa] = StrToFloat(StringReplace(Stampa.Text,'.', ',',
[rfReplaceAll]));
end;
procedure SimStop(PInput, POutput, PUser: PDLLParams);
// Routine viene eseguita solo in fase di chiusura
begin
end;
//export methods for ProfiLab
exports
SimStart,
SimStop,
NumInputs,
NumOutputs,
CalculateEx,
InputName,
OutputName,
ApriOpenDialog,
ApriSaveDialog;
begin
end.
procedure CalculateEx(PInput, POutput, PUser: PDLLParams; PStrings: PStringParams);
// Routine è permanente
var
input:string;
output:string;
s: shortstring;
begin
if PInput^[I0] > 2.5 then
begin
s := ApriOpenDialog;
if s <> '' then
CaricaArrayDaFile(s, POutput);
end;
if PInput^[I1] > 2.5 then
begin
s := ApriSaveDialog;
if s <> '' then
SalvaArrayInFile(s, POutput);
end;
PInput^[Leggi] = StrToFloat(StringReplace(input.Text,'.', ',',
[rfReplaceAll]));
POutput^[Stampa] = StrToFloat(StringReplace(output.Text,'.', ',',
[rfReplaceAll]));
end;
project1.lpr(129,22) Hint: Parameter "PInput" not used
project1.lpr(129,30) Hint: Parameter "POutput" not used
project1.lpr(129,39) Hint: Parameter "PUser" not used
project1.lpr(204,53) Error: Illegal qualifier
project1.lpr(205,21) Error: Illegal expression
project1.lpr(206,57) Error: Illegal qualifier
project1.lpr(207,21) Error: Illegal expression
project1.lpr(236) Fatal: There were 4 errors compiling module, stopping
Si perchè sto lavorando in ambiente grafico, non comandi per
ambiente a carattere (il vecchio MS DOS per intenderci).
Da una casella di testo c'è un solo
modo per Leggere il contenuto: es. Leggere.Text e per stampare Scrivere.Text:=Scrivere
Dovrebbe essere così...
Si ma ho degli errori :(
PInput^[Leggi] = StrToFloat(StringReplace(Leggere.Text,'.', ',',[rfReplaceAll]));
POutput^[Stampa] = StrToFloat(StringReplace(Scrivere.Text:=Scrivere,'.', ',',[rfReplaceAll]));
project1.lpr(129,22) Hint: Parameter "PInput" not used
project1.lpr(129,30) Hint: Parameter "POutput" not used
project1.lpr(129,39) Hint: Parameter "PUser" not used
project1.lpr(207,55) Error: Illegal qualifier
project1.lpr(207,85) Error: Illegal expression
project1.lpr(208,58) Error: Illegal qualifier
project1.lpr(208,62) Fatal: Syntax error, ")" expected but ":=" found
StringReplace(input.Text,'.', ',',
Non so dove tu veda il TEdit in queste dichiarazioni ... va bene usare le stringhe o i campi di edit ... ma nel modo corretto.
Qui usi il "confronto" come assegnazione.
Metti delle assegnazioni a caso ...
StringReplace(Scrivere.Text:=Scrivere
in
POutput^[Stampa] = StrToFloat(StringReplace(Scrivere.Text:=Scrivere,'.', ',',[rfReplaceAll]));
PInput^[Leggi] = StrToFloat
POutput^[Stampa] = StrToFloat
var
Leggere:Text;
Scrivere:Text;
Avevo già provato a dichiararle come Text ma non cambiava nulla.
Devo configurare l'ingresso della dll per fa acquisire le stringhe che invio.
Stessa cosa per l'uscita, le deve inviare ai display da quelli salvati
Ciao,
Attualmente ho modificato cosi:
procedure CalculateEx(PInput, POutput, PUser: PDLLParams; PStrings: PStringParams);
// Routine è permanente
var
s: string;
begin
if PInput^[I0] > 2.5 then
begin
s := ApriOpenDialog;
if s <> '' then
CaricaArrayDaFile(s, POutput);
end;
if PInput^[I1] > 2.5 then
begin
s := ApriSaveDialog;
if s <> '' then
SalvaArrayInFile(s, PInput);
end;
end;
esattamente questa stringa:
SalvaArrayInFile(s, PInput);
In questo modo quello che scrivo nella tabella lo legge e fino a qui va bene ma in più mi scrive un 1=5 che non so dove lo pesca e in più tutto l'indice del vettore da 1 a 100 cosa che non vorrei visualizzare.
0=0
1=5 questo da dove è uscito?
2=33434 questo numero l'ho scritto nella casella di testo OK
3=0
4=0
5=0
6=0
7=0
8=0
........n=100
In questo modo quello che scrivo nella tabella lo legge e fino a qui va bene ma in più mi scrive un 1=5 che non so dove lo pesca e in più tutto l'indice del vettore da 1 a 100 cosa che non vorrei visualizzare.
hai già verificato se nella posizione 1 c'è o no il valore 5?
per il resto che non vuoi visualizzare, basta che ci metti un if all'interno del loop, ad esempio:
for i := low(PDLLParams^) to high(PDLLParams^) do
if PDLLParams^[i] <> 0 then
sl.Values[ inttostr(i) ] := FloatToStr( PDLLParams^[i] );
Come faccio a verificarlo? l'elemento di posizione [] non cè.
attualmente nell'ingresso ho messo solo una casella quindi deve leggere solo un numero, però vorrei anche capire come fa a scegliersi lui l'indice del vettore per esempio in questo caso ha scritto nel 2=33434 e nel 1=5 questo l'ha generato da solo.
procedure SalvaArrayInFile(FileName: string; PAParams: PDLLParams);
var
i: integer;
sl: TStringList;
begin
sl := TStringList.Create;
try
for i := low(PAParams^) to high(PAParams^) do
sl.Values[IntToStr(i)] := FloatToStr(PAParams^[i]);
sl.SaveToFile(FileName);
finally
sl.Free;
end;
end;
procedure CaricaArrayDaFile(FileName: string; PAParams: PDLLParams);
var
i: integer;
sl: TStringList;
e: extended;
s: string;
begin
sl := TStringList.Create;
try
sl.LoadFromFile(FileName);
for i := low(PAParams^) to high(PAParams^) do
begin
s := sl.Values[IntToStr(i)];
e := StrToFloat(s);
PAParams^[i] := e;
end;
finally
sl.Free;
end;
end;
Ciao,
Non cambia nulla, ho provato a scrivere per esempio un "ciao", ma non lo salva.
Pare che salva solo numeri sempre nel solito indice.
TStringParams = array[0..100] of string; //Type of ProfiLab DLL parameters
PStringParams = ^TStringParams; // Pointer to ProfiLab DLL parameters
procedure SalvaArrayInFile(FileName: string; PAParams: PDLLParams);
var
i: integer;
sl: TStringList;
begin
i := 0;
sl := TStringList.Create;
try
for i := low(PAParams^) to high(PAParams^) do
sl.Values[IntToStr(i)] := FloatToStr(PAParams^[i]);
sl.SaveToFile(FileName);
finally
sl.Free;
end;
end;
procedure CaricaArrayDaFile(FileName: string; PAParams: PDLLParams);
var
i: integer;
sl: TStringList;
e: extended;
s: string;
begin
i := 0;
sl := TStringList.Create;
try
sl.LoadFromFile(FileName);
for i := low(PAParams^) to high(PAParams^) do
begin
s := sl.Values[IntToStr(i)];
e := StrToFloat(s);
PAParams^[i] := e;
end;
finally
sl.Free;
end;
end;
Ma se dovessi inserire PString dovrebbe risolvermi il problema? al posto di PInput e POutput?
Solo che dovrei modificare i 2 Array : CaricaArrayDaFile e SalvaArrayInFile
CaricaArrayDaFile(s, POutput);
SalvaArrayInFile(s, PInput);
procedure CalculateEx(PInput, POutput, PUser: PDLLParams; PStrings: PStringParams);
// Routine è permanente
var
s: string;
begin
if PInput^[I0] > 2.5 then
begin
s := ApriOpenDialog;
if s <> '' then
CaricaArrayDaFile(s, POutput);
end;
if PInput^[I1] > 2.5 then
begin
s := ApriSaveDialog;
if s <> '' then
SalvaArrayInFile(s, PInput);
end;
end;
Allora in parte ha tolto tutto l'indice ma lascia solo 1=5 e 2=345 rimangono quelli dove va a scrivere ma vorrei togliere anche 1= e 2=
:)
procedure SalvaArrayInFile(FileName: string; PAParams: PDLLParams);
var
i: integer;
sl: TStringList;
begin
sl := TStringList.Create;
try
for i := low(PAParams^) to high(PAParams^) do
if PAParams^[i] <> 0 then
sl.Values[IntToStr(i)] := FloatToStr(PAParams^[i]);
sl.SaveToFile(FileName);
finally
sl.Free;
end;
end;
ma nel display ci metti i valori leggendo dall'array o no?
anche perchè l'altra funzione, quella che legge dal file, salva i valori nell'array...
inizio a pensare di non averci capito nulla :-\
Edit:
comunque, nel caso, devi cambiare questa riga:
sl.Values[ inttostr(i) ] := FloatToStr( PDLLParams^[i] );
in questo modo:
sl.Add(FloatToStr( PDLLParams^[i] ));
Ciao,
ho fatto varie prove è ho verificato che nel momento che premo il pulsante per aprire il SaveDialog l'array acquisisce il valore 5 e lo stesso vale per l'OpenDialog.
Ora la mia domanda è : esiste un modo per evitare che l'array acquisisca questo valore 5 nel momento che premo il pulsante?
Vi ringrazio :)
procedure CalculateEx(PInput, POutput, PUser: PDLLParams; PStrings: PStringParams);
// Routine è permanente
var
i: integer;
sl: TStringList;
s: string;
begin
if PInput^[I0] > 2 then
begin
s := ApriOpenDialog;
if s <> '' then
CaricaArrayDaFile(s, POutput);
end;
if PInput^[I1] > 2 then
begin
s := ApriSaveDialog;
if s <> '' then
SalvaArrayInFile(s, PInput);
end;
end;
procedure SalvaArrayInFile(FileName: string; PAParams: PDLLParams);
var
i: integer;
sl: TStringList;
begin
sl := TStringList.Create;
try
for i := low(PAParams^) to high(PAParams^) do
if PAParams^[i] <> 0 then
sl.Add(FloatToStr(PAParams^[i]));
sl.SaveToFile(FileName);
finally
sl.Free;
end;
end;
procedure CaricaArrayDaFile(FileName: string; PAParams: PDLLParams);
var
i: integer;
sl: TStringList;
e: extended;
s: string;
begin
sl := TStringList.Create;
try
sl.LoadFromFile(FileName);
for i := low(PAParams^) to high(PAParams^) do
begin
s := sl.Values[IntToStr(i)];
e := StrToFloat(s);
PAParams^[i] := e;
end;
finally
sl.Free;
end;
end;
Salve squadra Lazarus :) ;)
Il 5 è stato affondato:)
procedure SalvaArrayInFile(FileName: string; PAParams: PDLLParams);
var
i: integer;
sl: TStringList;
begin
sl := TStringList.Create;
try
for i := low(PAParams^) to high(PAParams^) do
if i <> 5 then
Write(i);
if PAParams^[i] <> 0 then
sl.Add(FloatToStr(PAParams^[i]));
sl.SaveToFile(FileName);
finally
sl.Free;
end;
end;
Attualmente non riesco a leggere nel display quello che carico con OpenDialog, il tutto da quando ho tolto l'indice dell'array.
Per voi devo fare qualche modifica a:
procedure CaricaArrayDaFile(FileName: string; PAParams: PDLLParams);
var
i: integer;
sl: TStringList;
e: extended;
s: string;
begin
sl := TStringList.Create;
try
sl.LoadFromFile(FileName);
for i := low(PAParams^) to high(PAParams^) do
begin
s := sl.Values[IntToStr(i)];
e := StrToFloat(s);
PAParams^[i] := e;
end;
finally
sl.Free;
end;
end;
Grazie ciao
Ciao a tutti,
Ho inserito come const a Leggi e Stampa questo '' ma ho dei problemi ti tipo nelle 2 funzioni.
project1.lpr(115,12) Error: Constant and CASE types do not match
project1.lpr(115,12) Error: Ordinal expression expected
project1.lpr(115,12) Error: duplicate case label
project1.lpr(122,13) Error: Constant and CASE types do not match
project1.lpr(122,13) Error: Ordinal expression expected
project1.lpr(242) Fatal: There were 5 errors compiling module, stopping
ciao
const
Inputs = 3; // quantita entrata
Outputs = 1; // quantita uscita
{INPUTS}// nome per numero di entrata
I0 = 0; // valore I0 = PInput[I0] ossia PInput[0]
I1 = 0; // valore I1 = PInput[I1] ossia PInput[1]
Leggi = '';
// I3 = 3;
// ... I99 = 99;
{OUTPUTS}// nome per numero di uscita
Stampa = ''; // valore Q0 = POutput[Q0] ossia POutput[0]
function InputName(Channel: byte): ShortString; // trasferire nome di entrata
begin
case Channel of
I0: Result := 'Cerca'; // nome di pin I0
I1: Result := 'Salva'; // nome di pin I1
Leggi: Result := '$Leggi';
end;
end;
function OutputName(Channel: byte): ShortString; // trasferire nome di uscita
begin
case Channel of
Stampa: Result := '$Stampa'; // nome di pin Q0
//Q1: Result := 'Q1'; // nome di pin Q1
end;
end;
nomore ho bisogno che mi aiuti a farlo, anche perché c'e una funzione di mezzo.
function InputName(Channel: byte): ShortString; // trasferire nome di entrata
begin
case Channel of
I0: Result := 'Cerca'; // nome di pin I0
I1: Result := 'Salva'; // nome di pin I1
Leggi: Result := '$Leggi';
end;
end;
function OutputName(Channel: byte): ShortString; // trasferire nome di uscita
begin
case Channel of
Stampa: Result := '$Stampa'; // nome di pin Q0
//Q1: Result := 'Q1'; // nome di pin Q1
end;
end;
Non capisco che condizione devo dare, poi Result sarebbe il nome della funzione giusto?
function InputName(Channel: byte): ShortString;
if I0 = Result then 'Cerca' ;
if I1 = Result then 'Salva' ;
if Leggi = Result then '$Leggi';
function OutputName(Channel: byte): ShortString;
if Stampa = Result then '$Stampa';
function InputName(Channel: byte): ShortString; // trasferire nome di entrata
begin
case Channel of
I0: Result := 'Cerca'; // nome di pin I0
I1: Result := 'Salva'; // nome di pin I1
Leggi: Result := '$Leggi';
end;
end;
anche io ho bisogno di aiuto, non capisco che c'è da fare
insomma, togliendo il case dovresti scrivere:
// decommenta sotto nel caso Leggi sia un valore di default
// Result := '$Leggi';
if Channel = I0 then
Result := 'Cerca';
if Channel = I1 then
Result := 'Salva';
poi, da quello che hai scritto io capisco: "se Channel = Leggi".
Ma Leggi non è un canale, che ruolo ha allora?
Se è un valore di default decommenta come scritto sopra nel codice.
Il problema però non lo risolvi: la correzione sopra ti permette di compilare ma rimane il bug concettuale in quanto I0 e I1 hanno lo stesso valore (cioè 0) ==> sono lo stesso canale ==> la funzione (per Channel = 0) restituirà sempre e comunque "Salva".
Il "case" anche se non ti compila è giusto, il bug sta nel fatto che hai dichiarato questo:
const
{INPUTS}// nome per numero di entrata
I0 = 0; // valore I0 = PInput[I0] ossia PInput[0]
I1 = 0; // valore I1 = PInput[I1] ossia PInput[1]
Probabilmente I0 e I1 devono avere valori diversi, o no?
Si Leggi è un canale d'ingresso, ma ho problemi di tipo perché ho messo come nullo la costante Leggi e Stampa :)
project1.lpr(117,8) Error: Incompatible types: got "Byte" expected "AnsiString"
project1.lpr(128,8) Error: Incompatible types: got "Byte" expected "AnsiString"
project1.lpr(256) Fatal: There were 2 errors compiling module, stopping
const
Inputs = 3; // quantita entrata
Outputs = 1; // 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]
Leggi = '';
// I3 = 3;
// ... I99 = 99;
{OUTPUTS}// nome per numero di uscita
Stampa = '';
function InputName(Channel: byte): ShortString; // trasferire nome di entrata
begin
//case Channel of
if Channel = I0 then
Result := 'Cerca';
if Channel = I1 then
Result := 'Salva';
if Channel = Leggi then
Result := '$Leggi';
function OutputName(Channel: byte): ShortString; // trasferire nome di uscita
begin
//case Channel of
if Channel = Stampa then
Result := '$Stampa';
STRINGHE
NUMERI
function OutputName(Channel: byte): ShortString; // trasferire nome di uscita
Che siano stringhe vuote o meno, il compilatore ti avvisa che stai confrontando tipo diversi e incompatibli.
Leggi = $01;
Stampa = '$02;
Con sto leggi e stampa stai facendo un casino pazzesco.
Inizia con dare nomi alle variabili che ti aiutino a capire cosa stai facendo.
NomeDellPinLeggi = '';
NomeDellPinStampa = '';
NumeroDelPinLettura=$01;
NumeroDelPinStampa=$02;
Sono gratis i caratteri, non hai problemi ad aggiungere linee di comunicazione tra le funzioni.
Stilgar
Grazie Nomore e Stilgar vi ho stressato fin troppo, se Legolas puo farmi un piacere è meglio poichè ha provato il software.
Ciao Legolas hai tempo di provare la dll e verificare perchè non salva bene e non legge?
Ho allegato la parte di profilab manca da caricare la dll e provare. :)
Grazie
library project1;
{$mode objfpc}{$H+}
uses
Interfaces,
Classes,
SysUtils,
Windows,
FileUtil,
Forms,
Controls,
Graphics,
Dialogs,
ShellApi;
const
Inputs = 3; // quantita entrata
Outputs = 1; // 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]
Leggi = 2;
// I3 = 3;
// ... I99 = 99;
{OUTPUTS}// nome per numero di uscita
Stampa = 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
TStringParams = array[0..100] of PChar; //Type of ProfiLab DLL parameters
PStringParams = ^TStringParams; // Pointer to ProfiLab DLL parameters
function ApriSaveDialog: ShortString;
begin
Result := '';
if not assigned(globalDialog) then
begin
globalDialog := TSaveDialog.Create(nil);
try
globalDialog.DefaultExt := 'txt';
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.DefaultExt := 'txt';
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
Leggi: Result := '$Leggi';
end;
end;
function OutputName(Channel: byte): ShortString; // trasferire nome di uscita
begin
case Channel of
Stampa: Result := '$Stampa'; // 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
end;
procedure SalvaArrayInFile(FileName: string; PAParams: PDLLParams);
var
i: integer;
sl: TStringList;
begin
sl := TStringList.Create;
try
for i := low(PAParams^) to high(PAParams^) do
if i <> 5 then
Write(i);
if PAParams^[i] <> 0 then
sl.Add(FloatToStr(PAParams^[i]));
sl.SaveToFile(FileName);
finally
sl.Free;
end;
end;
procedure CaricaArrayDaFile(FileName: string; PAParams: PDLLParams);
var
i: integer;
sl: TStringList;
e: extended;
s: string;
begin
sl := TStringList.Create;
try
sl.LoadFromFile(FileName);
for i := low(PAParams^) to high(PAParams^) do
begin
s := sl.Values[IntToStr(i)];
e := StrToFloat(s);
PAParams^[i] := e;
end;
finally
sl.Free;
end;
end;
procedure CalculateEx(PInput, POutput, PUser: PDLLParams; PStrings: PStringParams);
// Routine è permanente
var
i: integer;
sl: TStringList;
s: string;
begin
if PInput^[I0] > 2.5 then
begin
s := ApriOpenDialog;
if s <> '' then
CaricaArrayDaFile(s, POutput);
end;
if PInput^[I1] > 2.5 then
begin
s := ApriSaveDialog;
if s <> '' then
SalvaArrayInFile(s, PInput);
end;
end;
procedure SimStop(PInput, POutput, PUser: PDLLParams);
// Routine viene eseguita solo in fase di chiusura
begin
end;
//export methods for ProfiLab
exports
SimStart,
SimStop,
NumInputs,
NumOutputs,
CalculateEx,
InputName,
OutputName,
ApriOpenDialog,
ApriSaveDialog;
begin
end.
Allora, ho spulciato per benino il progettino e i sorgenti della dll. Mi incuriosiva il problema del 5 non voluto. Da dove viene? Nella dll abbiamo 3 canali di input e 1 di output. I canali di input sono così impiegati:
Canale 1 -> tasto salva
Canale 2 -> tasto carica
Canale 3 -> campo "Leggi"
Il canale di output invece è impiegato per la casella di testo "Stampa"
Nella procedura di salvataggio dell'array viene salvato lo stato dei 3 canali di input. Il 5 è lo stato di "premuto" del tasto di apertura della dialog.
Nella procedura di caricamento dell'array da file viene copiato il contenuto dei 3 canali di input sui canali di output. Siccome il primo canale di input (cioè lo stato del tasto che apre la dialog) è 5, allora il valore 5 viene copiato nel primo canale di output. Per questo motivo ti trovi quel 5 non voluto.
Soluzione? Trovare un sistema più consono per il salvataggio e il caricamento dei dati. Potresti ad esempio provare a salvare solo i canali che ti servono, sia input che output.
Devi anche fare in modo che le dialog non rimangano sempre aperte, cosa che adesso succede. Nell'esempio di dll in delphi c'è qualcosa a riguardo. Dovrebbe essere qualcosa di simile:
if PInput^[I0] > 2.5 then
begin
if (PInput^[I0] > 2.5) and not(PUser^[U0] > 2.5) then
begin
s := ApriOpenDialog;
if s <> '' then
CaricaArrayDaFile(s, POutput);
end;
PUser^[U0]:=PInput^[I0];
fermo restando che c'è da modificare CaricaArrayDaFile e SalvaArrayInFile
Ciao Legolas,
Se il valore 5 lo salvi dal canale 1 degli input, perché poi lo assegni al canale 1 degli output?
Mi puoi indicare dove lo sto assegnando?
dici qua? oppure devo modificare le costanti?
function OutputName(Channel: byte): ShortString; // trasferire nome di uscita
begin
case Channel of
Stampa: Result := '$Stampa'; // nome di pin Q0
//Q1: Result := 'Q1'; // nome di pin Q1
end;
end;
invece di salvare tutto l'array, ti salvi soltanto i valori che ti servono, ad esempio il canale 3 degli input e il canale 1 dell'output.
Questa modifica la devo fare qui?
procedure SalvaArrayInFile(FileName: string; PAParams: PDLLParams);
var
i: integer;
sl: TStringList;
begin
sl := TStringList.Create;
try
for i := low(PAParams^) to high(PAParams^) do
if PAParams^[i] <> 0 then
sl.Add(FloatToStr(PAParams^[i]));
sl.SaveToFile(FileName);
finally
sl.Free;
end;
end;
procedure CaricaArrayDaFile(FileName: string; PAParams: PDLLParams);
var
i: integer;
sl: TStringList;
e: extended;
s: string;
begin
sl := TStringList.Create;
try
sl.LoadFromFile(FileName);
for i := low(PAParams^) to high(PAParams^) do
begin
s := sl.Values[IntToStr(i)];
e := StrToFloat(s);
PAParams^[i] := e;
end;
finally
sl.Free;
end;
end;
PUser[U0] è una variabile di appoggio in cui viene inserito lo stato precedente del tasto, così sai se è già stato premuto e non riapre la dialog se non serve
Attualmente si apre e si chiude bene, ma una volta aperto i dialog non posso più riaprili :o
Ti ringrazio :)
Ti allego tutta la dll che ho modificato
library project1;
{$mode objfpc}{$H+}
uses
Interfaces,
Classes,
SysUtils,
Windows,
FileUtil,
Forms,
Controls,
Graphics,
Dialogs,
ShellApi;
const
Inputs = 3; // quantita entrata
Outputs = 1; // 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]
Leggi = 2;
// I3 = 3;
// ... I99 = 99;
{OUTPUTS}// nome per numero di uscita
Stampa = 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
TStringParams = array[0..100] of PChar; //Type of ProfiLab DLL parameters
PStringParams = ^TStringParams; // Pointer to ProfiLab DLL parameters
function ApriSaveDialog: ShortString;
begin
Result := '';
if not assigned(globalDialog) then
begin
globalDialog := TSaveDialog.Create(nil);
try
globalDialog.DefaultExt := 'txt';
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.DefaultExt := 'txt';
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
Leggi: Result := '$Leggi';
end;
end;
function OutputName(Channel: byte): ShortString; // trasferire nome di uscita
begin
case Channel of
Stampa: Result := '$Stampa'; // 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
end;
procedure SalvaArrayInFile(FileName: string; PAParams: PDLLParams);
var
i: integer;
sl: TStringList;
begin
sl := TStringList.Create;
try
for i := low(PAParams^) to high(PAParams^) do
if PAParams^[i] <> 0 then
sl.Add(FloatToStr(PAParams^[i]));
sl.SaveToFile(FileName);
finally
sl.Free;
end;
end;
procedure CaricaArrayDaFile(FileName: string; PAParams: PDLLParams);
var
i: integer;
sl: TStringList;
e: extended;
s: string;
begin
sl := TStringList.Create;
try
sl.LoadFromFile(FileName);
for i := low(PAParams^) to high(PAParams^) do
begin
s := sl.Values[IntToStr(i)];
e := StrToFloat(s);
PAParams^[i] := e;
end;
finally
sl.Free;
end;
end;
procedure CalculateEx(PInput, POutput, PUser: PDLLParams; PStrings: PStringParams);
// Routine è permanente
var
i: integer;
sl: TStringList;
s: string;
begin
if PInput^[I0] > 2.5 then
begin
if (PInput^[I0] > 2.5) and not (PUser^[U0] > 2.5) then
begin
s := ApriOpenDialog;
if s <> '' then
CaricaArrayDaFile(s, POutput);
end;
PUser^[U0] := PInput^[I0];
end;
if PInput^[I1] > 2.5 then
begin
if (PInput^[I1] > 2.5) and not (PUser^[U0] > 2.5) then
begin
s := ApriSaveDialog;
if s <> '' then
SalvaArrayInFile(s, PInput);
end;
PUser^[U0] := PInput^[I1];
end;
end;
procedure SimStop(PInput, POutput, PUser: PDLLParams);
// Routine viene eseguita solo in fase di chiusura
begin
end;
//export methods for ProfiLab
exports
SimStart,
SimStop,
NumInputs,
NumOutputs,
CalculateEx,
InputName,
OutputName,
ApriOpenDialog,
ApriSaveDialog;
begin
end.
Se il valore 5 lo salvi dal canale 1 degli input, perché poi lo assegni al canale 1 degli output?
Mi puoi indicare dove lo sto assegnando?
dici qua? oppure devo modificare le costanti?
Lo assegni in CaricaArrayDaFile. La funzione che salva l'array, spiego in parole povere, prende lo stato dei vari controlli DI INPUT (i due push button e il numeric input) e li salva su file in ordine:
riga 1 -> salva lo stato del push button 1
riga 2 -> salva lo stato del push button 2
riga 3 -> salva lo stato del numeric input
riga 4 -> 0
riga 5 -> 0
...
riga 99 -> 0
riga 100 -> 0
La funzione che carica i dati nell'array prende il file appena creato e lo carica nei controlli DI OUTPUT (in questo caso ce n'è solo uno, cioè il display):
riga 1 -> carica il valore di push button 1 in display
riga 2 -> carica il valore di push button 2, ma non viene utilizzato perché non ci sono altri controlli di output
riga 3 -> carica il valore di numeric input, ma non viene utilizzato perché non ci sono altri controlli di output
riga 4 -> carica il valore 0, ma non viene utilizzato perché non ci sono altri controlli di output
...
riga 99 -> carica il valore 0, ma non viene utilizzato perché non ci sono altri controlli di output
riga 100 -> carica il valore 0, ma non viene utilizzato perché non ci sono altri controlli di output
invece di salvare tutto l'array, ti salvi soltanto i valori che ti servono, ad esempio il canale 3 degli input e il canale 1 dell'output.
Questa modifica la devo fare qui?
procedure SalvaArrayInFile(FileName: string; PAParams: PDLLParams);
var
i: integer;
sl: TStringList;
begin
sl := TStringList.Create;
try
for i := low(PAParams^) to high(PAParams^) do
if PAParams^[i] <> 0 then
sl.Add(FloatToStr(PAParams^[i]));
sl.SaveToFile(FileName);
finally
sl.Free;
end;
end;
procedure CaricaArrayDaFile(FileName: string; PAParams: PDLLParams);
var
i: integer;
sl: TStringList;
e: extended;
s: string;
begin
sl := TStringList.Create;
try
sl.LoadFromFile(FileName);
for i := low(PAParams^) to high(PAParams^) do
begin
s := sl.Values[IntToStr(i)];
e := StrToFloat(s);
PAParams^[i] := e;
end;
finally
sl.Free;
end;
end;
Esattamente. In questo caso ti salvi solo i due valori che ti servono e te li ricarichi assegnandoli ai controlli esatti
Attualmente si apre e si chiude bene, ma una volta aperto i dialog non posso più riaprili :o
In effetti c'è un piccolo "baco" nel codice che ti ho scritto (e un altro lo hai aggiunto tu). Prova così:
procedure CalculateEx(PInput, POutput, PUser: PDLLParams; PStrings: PStringParams);
// Routine è permanente
var
sl: TStringList;
s: string;
begin
if PInput^[I0] > 2.5 then
begin
if (PInput^[I0] > 2.5) and not (PUser^[U0] > 2.5) then
begin
s := ApriOpenDialog;
if s <> '' then
CaricaArrayDaFile(s, POutput);
end;
end;
PUser^[U0] := PInput^[I0];
if PInput^[I1] > 2.5 then
begin
if (PInput^[I1] > 2.5) and not (PUser^[U1] > 2.5) then
begin
s := ApriSaveDialog;
if s <> '' then
SalvaArrayInFile(s, PInput);
end;
end;
PUser^[U1] := PInput^[I1];
end;
Tieni anche presente che i due button rimangono premuti perché il controllo passa alle dialog, quindi devi ripremerli una prima volta per "sbloccarli", dopodiché funzionano alla perfezione
Ciao, :)
Allora se voglio salvare solo l'ingresso 3 quindi (riga 3 -> salva lo stato del numeric input)
dovrei fare cosi:
Ma qunado salvo non vedo niente nel file di testo.
Ho provato così:
e giustamente mi salva i tre ingressi e vedo il 5 e il numero che inserisco nella casella.
Per l'uscita ho fatto così:
procedure SalvaArrayInFile(FileName: string; PAParams: PDLLParams);
var
i: integer;
sl: TStringList;
begin
sl := TStringList.Create;
try
for i := 3 to 3 do
if PAParams^[i] <> 0 then
sl.Add(FloatToStr(PAParams^[i]));
sl.SaveToFile(FileName);
finally
sl.Free;
end;
end;
procedure CaricaArrayDaFile(FileName: string; PAParams: PDLLParams);
var
i: integer;
sl: TStringList;
e: extended;
s: string;
begin
sl := TStringList.Create;
try
sl.LoadFromFile(FileName);
for i := 0 to 1 do
begin
s := sl.Values[IntToStr(i)];
e := StrToFloat(s);
PAParams^[i] := e;
end;
finally
sl.Free;
end;
end;
Legolas, c'è anche una cosa che non capisco:
Come mai appena abilito la simulazione in aiutomatico il display si setta a 0?
Dipende dalla costante $Stampa=0?
Ti Saluto