I want to do the following behavior in one delphi application.(10.3+)
I want a user to have the possibility to implement his own logical behavior of a program "saved in options".
Very similar with an arduino logical/program.
For example
I create a program that is keep tracking values about 10 heat sensors. But it can be anything.
The program has a timer and in the on timer event the following actions are taking places.
read the values from sensors
take action if needed
there are 2 types of info saved in this class.
Non Changing informations like ID name etc, and permanent changing (DATA).
here is the example of the base class that hold all the info from one sensor.
type TXXX = class
private
public
// info that are not changing ever
property ID : Integer ...
property SENSOR_NAME : String ...
// info that are constantly changing
property READ_TIMESTAMP : TDateTime ...
property CURRENT_VALUE : Double ...
property VALUE_SUPREMUM : Double ...
property VALUE_INFIMUM : Double ...
end
I need to create some sort of options of the program when a user can define his own logical that the program should respond if condition are meet.
for example a user want to say:
if CURRENT_VALUE > 5 and VALUE_INFIMUM > 0.5 then begin
"take action 1"
end
and so on...
"take action x" and all the actions are hardcoded. for example close/open a valve.
now these properties are more than 4 are like 50 or so.
anyone can point me some directions?
Regards
Razvan
There are 2 ways how you can solve your problem.
1st: You can use some of scripting engines. That’s the direct purpose of this components. You can use something like Pascal Script For Delphi (https://www.remobjects.com/ps.aspx), Fast script (https://www.fast-report.com/en/product/fast-script/), TMS Scripter (https://www.tmssoftware.com/site/scriptstudiopro.asp), etc.
2nd: If you have limited actions and condition – you can write your own parser and GUI for it for handle all this staff.
Make expressions parser, declare operants (numbers or allowed properties of your sensors, or other expression), declare mathematical operations (plus, mines...) and logical operation (Lower, higer, equal, and, not, or). It's can take a while to implement it, but you can build very user-friendly wizard to manage it.
Related
I've just watched a talk on security considerations for railway systems from last year's 32C3.
At minute 25 the speaker briefly talks about Ada. Specifically he says:
Typical Ada implementations have a mechanism called "(tramp / trunk /
?) lines". And that means it will execute code on [the] stack which is
not very good for C programs. And [...] if you want to link Ada code with C
libraries, one of the security mechanisms won't work.
Here is a link (YouTube) to the respective part of the talk. This is the slide in the background. As you see I am unsure about one of the words. Perhaps it's trampolines?
Now my blunt question: Is there any truth in this statement? If so, can anyone elaborate on this mysterious feature of the Ada language and the security mechanism it apparently influences?
Until now I always assumed that code lives in a code segment (aka "text") whereas data (including the stack) is placed in a data segment at a different memory location (as depicted in this graphic). And reading about memory management in Ada suggests it should not be much different there.
While there are ways to circumvent such a layout (see e.g. this "C on stack" question and this "C on heap" answer), I believe modern OSes would commonly prevent such attempts via executable space protection unless the stack is explicitly made executable. - However, for embedded systems it may be still an issue if the code is not kept on ROM (can anyone clarify?).
They're called "trampolines". Here's my understanding of what they're for, although I'm not a GNAT expert, so some of my understanding could be mistaken.
Background: Ada (unlike C) supports nested subprograms. A nested subprogram is able to access the local variables of enclosing subprograms. For example:
procedure Outer is
Some_Variable : Integer;
procedure Inner is
begin
...
Some_Variable := Some_Variable + 1;
...
Since each procedure has its own stack frame that holds its own local variables, there has to be a way for Inner to get at Outer's stack frame, so that it can access Some_Variable, either when Outer calls Inner, or Outer calls some other nested subprograms that call Inner. A typical implementation is to pass a hidden parameter to Inner, often called a "static link", that points to Outer's stack frame. Now Inner can use that to access Some_Variable.
The fun starts when you use Inner'Access, which is an access procedure type. This can be used to store the address of Inner in a variable of an access procedure type. Other subprograms can later use that variable to call the prodcedure indirectly. If you use 'Access, the variable has to be declared inside Outer--you can't store the procedure access in a variable outside Outer, because then someone could call it later, after Outer has exited and its local variables no longer exist. GNAT and other Ada compilers have an 'Unrestricted_Access attribute that gets around this restriction, so that Outer could call some outside subprogram that indirectly calls Inner. But you have to be very careful when using it, because if you call it at the wrong time, the result would be havoc.
Anyway, the problem arises because when Inner'Access is stored in a variable and later used to call Inner indirectly, the hidden parameter with the static link has to be used when calling Inner. So how does the indirect caller know what static link to pass?
One solution (Irvine Compiler's, and probably others) is to make variables of this access type have two values--the procedure address, and the static link (so an access procedure is a "fat pointer", not a simple pointer). Then a call to that procedure will always pass the static link, in addition to other parameters (if any). [In Irvine Compiler's implementation, the static link inside the pointer will be null if it's actually pointing to a global procedure, so that the code knows not to pass the hidden parameter in that case.] The drawback is that this doesn't work when passing the procedure address as a callback parameter to a C routine (something very commonly done in Ada libraries that sit on top of C graphics libraries like gtk). The C library routines don't know how to handle fat pointers like this.
GNAT uses, or at one time used, trampolines to get around this. Basically, when it sees Inner'Unrestricted_Access', it will generate new code (a "trampoline") on the fly. This trampoline calls Inner with the correct static link (the value of the link will be embedded in the code). The access value will then be a thin pointer, just one address, which is the address of the trampoline. Thus, when the C code calls the callback, it calls the trampoline, which then adds the hidden parameter to the parameter list and calls Inner.
This solves the problem, but creates a security issue when the trampoline is generated on the stack.
Edit: I erred when referring to GNAT's implementation in the present tense. I last looked at this a few years ago, and I don't really know whether GNAT still does things this way. [Simon has better information about this.] By the way, I do think it's possible to use trampolines but not put them on the stack, which I think would reduce the security issues. When I last investigated this, if I recall correctly, Windows had started preventing code on the stack from being executed, but it also allowed programs to request memory that could be used to dynamically generate code that could be executed.
A presentation in 2003 on Ada for secure applications (D. Wheeler, SigAda 2003) supports this on page 7 : (quote)
How do Ada and security match poorly?
...
Ada implementations typically need to execute code on the stack("trampolines", e.g. for access values to nested subprograms).
In other (C) words, for function pointers, where the subprograms are nested within other subprograms.
(Speculating : presumably these function pointers are on the stack so they go out of scope when you leave the scope of the outer subprogram)
HOWEVER
A quick search also showed this gcc mailing list message :
[Ada] remove trampolines from front end
dated 2007, which refers to enabling Gnat executables to run on systems with DEP (data execution protection), by eliminating precisely this problematic feature.
This is NOT an authoritative answer but it seems that while "typical" Ada implementations do (or did) so, it may not be the case for at least Gnat this side of 2007, thanks to protection systems on newer hardware driving the necessary changes to the compiler.
Or : definitely true at one time, but possibly no longer true today, at least for Gnat.
I would welcome a more in-depth answer from a real expert...
EDIT : Adam's thorough answer states this is still true of Gnat, so my optimism should be tempered until further information.
FSF GCC 5 generates trampolines under circumstances documented here. This becomes problematic when the trampolines are actually used; in particular, when code takes ’Access or ’Unrestricted_Access of nested subprograms.
You can detect when your code does this by using
pragma Restrictions (No_Implicit_Dynamic_Code);
which needs to be used as a configuration pragma (although you won’t necessarily get warnings at compilation time, see PR 67205). The pragma is documented here.
You used to set configuration pragmas simply by including them in a file gnat.adc. If you’re using gnatmake you can also use the switch -gnatec=foo.adc. gprbuild doesn’t see gnat.adc; instead set global configurations in package Builder in your project file,
package Builder is
for Global_Configuration_Pragmas use "foo.adc";
end Builder;
Violations end up with compilation errors like
$ gprbuild -P trampoline tramp
gcc -c tramp.adb
tramp.adb:26:12: violation of restriction "No_Implicit_Dynamic_Code" at /Users/simon/cortex-gnat-rts/test-arduino-due/gnat.adc:1
I am using Delphi 7, when I write code in the unit, I want autocomplete the words of the tree's objects.
For example, I have the next objets: LabelName, LabelEdge, LabelWindow, I want start write LabelN and have the possibility of autocomplete to LabelName.
Is it possible?
As David Heffernan said in the comments you need to press the CTRL+Space key in order for code insight to provide you with available choices for auto-completion.
The available choices then depend on the part of the component name, method name, variable name, or constant name you have already written.
They also depend on your current code scope which means that code insight won't provide you choice to use some method, variable or constant if it can't be accessed from the method you are writing code in (local variables/constants that belong to other methods, private members of a different class, etc.)
You can invoke code insight to provide you choices even when you haven't written any partial name. In this case code insight will show you all available methods, variables, constants and objects (both components and classes) that can be accessed from within the current code scope. This is most useful when you are searching for specific method but you can't remember its name.
I am using VS 2010; all these days I am confortable runnig code analysis on class libraries.
But for a web application, the UI control names with prefixes like ddl, pnl, etc are causing code analysis warnings as "Correct the spelling...". I googled and think this can be addressed using rulesets; but didn't find a way to suppress these..any pointers ?
You could add them to a custom dictionary.
Why are you using those prefixes?
The most common reason I've seen people give for this is "Hungarian Notation." However, as I've tried to point out in a number of jobs over the years, "you're doing it wrong." Within an IDE like VS 2010, is there any real reason to prefix every DropDownList instance with "ddl"? Both you and the IDE know it's a DropDownList. There's no question or confusion about that.
The idea behind Hungarian Notation isn't to "prefix every variable with a shorthand of its class" but rather to "prefix every variable with what it is." What something is doesn't have to mean its class or type, it's more an idea of what that object intuitively represents. Sure, it's a DropDownList. But what does that DropDownList mean? Is it part of a particular grouping of elements in the UI? That grouping's designation would provide a lot more information than "ddl" ever would.
As an example, say I have an application with various connection strings. In a given method in my DAL, I store one of them in a variable called strConnection. Well, that's adhering to the notation, but it's not telling me anything important. I know it's a string. (I can see its declaration, I can mouse over it in the IDE, etc.) And I know it's a connection string based on its usage. But which one is it? What part of the business does it serve? If instead it was called connstringHR then I could immediately infer that it's the connection string for the HR database.
Just recently, probably because I've been maintaining some old code, I've started to look at how / why I do things. As you do.
Most of my Delphi programming has been picked up in house, or from examples scattered across the web or manuals. And in some things are done just because "that's how I do it"
What I'm currently wondering about is Declaration, of variables, procedures, functions, etc.
When I am working with a form, I will place all my procedures and functions under public or private. Whilst I will try to avoid global vars and constants will generally go under var or const, either in the interface or implementation, depending on where they need to be called (occasionally though they will go in public / private)
Otherwise, if its just a unit I will declare the procedure in the interface and use in the implementation. Some of the code I've been maintaining recently has no interface declaration but instead has everything properly ordered with calls after procedures...
Is there a correct way to do this? Are there rules of what should / should not go in the class? Or is it a style / when you started thing?
Edit to add
My question is not about whether a declaration of a procedure goes in private/public but whether all declarations in a TForm Unit should go in one of these. Similarly should var / const be in one or the other?
Further clarification
I understand that not declaring in interface, or declaring in public/private/etc affects the visibility of procedures/functions to other units in my applicaiton.
The core of my question is why would i not want to declare? - especially when working in a form/unit when placing in private is much more explicit that the thing declared is not available to other units...
Cheers
Dan
Everything that can have a different value depending on the concrete instance belongs to the class, i.e.
TDog = class
strict private
FColor : TColor;
FName : String;
public
property Color : TColor read FColor write FColor;
property Name : String read FName write FName;
end;
Color and name are clearly attributes of each dog (and each dog will have other values here).
General rules:
Fields belong in private (visible in this class and in this unit) or strict private (visible only in this class)
If you need access to fields from other classes, create a public property. This gives you the freedom to change the simple field access to a more sophisticated getter / setter method lateron without changing the interface of your class.
Everything should be as local as possible. If private is enough, there's no need to make it protected (visible in subclasses too). And only make those things public that you really need from the outside.
Forms: only those things that you want to be stored in the DFM file should be published.
Put as much as you can in the implementation section and as little as you can in the interface section. This is also true for uses clauses.
You might be confusing the term global variable. If it's declared in a class it's not a global variable (even if declared public). Global variables (which you correctly consider good to avoid) always go in a var section either in the interface or the implementation section (which is preferrable following the general rules above)
The question seems to deal with scope. In other words, how easily accessible things can or should be.
As a general guideline, you want to reduce the scope of things as much as possible but still keep them accessible enough to be reused. The reason for this is:
that as your system grows and becomes more complex, the things that have are larger scope are more easily accessible.
as a result, they are more likely to be reused in an uncontrolled fashion.
(sounds great) but the problem comes when you want to make changes, and many things use that which you want to change...
it becomes far more difficult to make your changes without breaking something else.
Having said that, there is also a distinction between data (variables, constants, class fields, record attributes) and routines (functions, procedures, methods on classes). You'll want to apply the guidelines far more strictly to data because 'strange use' of data could interfere with some of your routines in highly unexpected and hard to debug ways.
Another thing to bear in mind is the special distinction between global variables and class fields or record attributes:
using global variables there is only one 'value' (term used loosely) for the entire application.
using class fields or record attributes, each new instance of the class or record has its own values independent of other instances.
This does seem to imply that you could use some form of global whenever your application only needs one thing. However, as alluded to earlier: this is not the only reason to avoid globals.
Personally I even tend to avoid global routines.
I'm frequently discovering that things that seemed okay declared global are not as universal as first thought. (E.g. Delphi VCL declares a global Screen object, I work on 2 screens; and many of our clients use 4 to 6.)
I also find it useful to associate routines that could have been global with specific classes as class methods. It generally makes it easier to understand the code.
So listing these 'locations' from largest scope to smallest, you would generally strive to pick locations lower down in the list (especially for data).
interface global
implementation global
interface threadvar
implementation threadvar
published (Note I don't really consider this to be a scope identifier; it's really public scope; "and includes RTTI information" - theoretically, it would be useful to also mark some private attributes as "include RTTI".)
public
protected
private
strict private
local variable
I must confess: what I have presented here is most certainly an over-simplification. It is one thing to know the goals, another to actually implement them. There is a balancing act between encapsulation (hiding things away) and exposing controlled interfaces to achieve high levels of re-usability.
The techniques to successfully balance these needs fall into a category of far more complicated (and sometimes even contentious) questions on system design. A poor design is likely to induce one to expose 'too much' with 'too large' a scope, and (perhaps paradoxically) also reduce re-usability.
In one of the Delphi demo applications, I've stumbled upon some syntax that I didn't know the Delphi compiler accepted:
// ......\Demos\DelphiWin32\VCLWin32\ActiveX\OleAuto\SrvComp\Word\
// Main.pas, line 109
Docs.Add(NewTemplate := True); // note the assignment
I can't seem to reproduce this type of parameter passing in my own code, and I never see anyone use it. So these are my questions:
Can i use this in "normal" methods and is it part of "the Delphi Language", or is this some compiler hack for automation objects?
What's needed in order to be able to use this?
Is this anything like C#4's named and optional parameters?
Additional information: I usually pass
records or simple classes when there
are many optional parameters to
methods, but it looks like I wouldn't
need that with this syntax. I'm aware
of default parameter values, but their
usefulness is limited because you
cannot provide any parameters to the
right of an omitted one. In JavaScript
I'm using this named parameter style
all the time (be it with different
syntax), and it's powerful.
Clearly the Delphi language supports named parameters since they appear right there in sample Delphi code. Delphi supports named parameters on automation objects, which are objects that implement the IDispatch interface. There are restrictions on the types the parameters and return types can have; in particular, they can't be Delphi classes.
I don't think the convenience you seek from named parameters would outweigh the performance hit you'd take by having every method call routed through the IDispatch.Invoke method. A call may also need to use GetIDsOfNames first. You don't see this in more code because late binding is usually something people try to avoid. Use early binding whenever possible to avoid the cost of looking up dispatch IDs and indirect method invocations.
Delphi supports optional parameters in non-automation code by allowing default values. You can omit the actual parameters for any parameter with a default value as long as you also omit the actual parameters of all subsequent parameters — the compiler ensures that a function's declaration allows for that.
I think optional parameters are overrated. They save time for the (one) person writing the code, but not for the (many) people reading the code. Whoever's reading it needs to know what the default values will be of any unspecified parameters, so you may as well just provide all the values explicitly anyway.
If you declare your procedure like so:
procedure DoSomething(AParam : integer = 0);
... it will assume a value of 0 for the parameter if it isn't given. As I recall, parameters with default values have to be at the end of the call, so like this:
procedure DoSomething(AFirstParam : string; AParam : integer = 0);
not like this:
procedure DoSomething(AParam : integer = 0; ASecondParam : string);
It is basically "some compiler hack for automation objects". I sometimes have to use it for Excel and Word automation.
e.g.
MSExcel.Application.Cells.Replace(What:='', Replacement:='', LookAt:=xlPart,
SearchOrder:=xlByRows, MatchCase:=False, SearchFormat:=True, ReplaceFormat:=True);
Is equivalent to VBA
Application.Cells.Replace(What='', Replacement='', LookAt=xlPart, _
SearchOrder=xlByRows, MatchCase=False, SearchFormat=True, ReplaceFormat=True)