Setting entry point in DWScript - delphi

Is there a way to set an entry point in DWScript?
For example, if I start a script execution, I'd like it to execute a procedure Main, rather than the code in the regular entry point (begin ... end.).
I know it's possible to execute functions from Delphi, but I'm not sure this would be quite the same.

Aside from writing your procedure Main(); and then having your regular script entry point consist of nothing but calling Main, which is probably not what you're thinking of, no, there's no way to do that in DWS.
For all its innovations in syntax, DWS is still Pascal, and it still works the way Pascal works. Asking for some sort of named Main routine would be a radical departure from Pascal style.
EDIT: To answer the clarification posted in comments:
If you want your script to spawn a new script thread, you'll have to handle it in external Delphi code. As of this writing, the DWS system doesn't have any concept of multithreading built in. If you wanted to do it, you'd do something like this:
Create an external routine called something like SpawnThread(EntryPoint: string). Its eval method (out in Native-Delphi-land) would spawn a new thread that loads the current script, then finds the routine with the specified name and executes it.
That's about the only way you could get it to work without language-level support. If you'd like a way to spawn threads from within DWS, try adding it as a feature request to the issue tracker.

Calling functions directly is explicited in
https://code.google.com/p/dwscript/wiki/FirstSteps#Functions
If you want to execute a function in a different thread, you'll need some Delphi-side code to create a new thread, a new execution, and then call your functions. The main and threaded-execution will then be sandboxed from each other (so can't share share global vars etc.).
If you need to share data between the threads, you could do that by exposing functions or external variables, which would call into Delphi code with the proper synchronizations and locks in place (what is "proper" will depend on what your code wants to do, like always in multithreading...).
Note that it is possible to pass objects, interfaces and dynamic arrays between script executions (provided they're executions of the same program), but just like with regular code, you'll have to use locks, critical sections or mutexes explicitly.

Related

Is it possible to modify command line parameters programmatically in Delphi?

I'm working with some legacy code that uses ParamCount() and ParamStr() in various places, and now I need to provide different values than those that were actually passed as command line variables.
The simplest solution would be to programmatically add/modify the existing command line parameters, since the alternative is to change A LOT of the legacy code to accept function parameters rather than directly accessing ParamCount() and ParamStr().
Is this possible? Can I somehow add/modify parameters from within the program itself so that ParamCount() ParamStr() will pick up my new/modified parameters?
Edit, clarification of the legacy code:
The legacy code makes some database requests, using where arguments from the command line (and sanitizing them). This is fine in 99.9% of all cases, as these arguments are fundamental for the purpose of the legacy units. However, I'm working on a new feature that "breaks the mold", where one of these fundamental arguments are unknown and need to be fetched from the database and provided internally.
Yes, I could search and replace, but my objective here is to not touch the legacy code, as it's in a unit that is shared among many different programs.
Restarting the program and/or executing a new copy of it from itself is one solution, but seems a bit risky and cumbersome. This is a production program that executes on a server and needs to be as simple and robust as possible.
Is this possible? Can I somehow add/modify parameters from within the program itself so that ParamCount() ParamStr() will pick up my new/modified parameters?
Technically yes, but it is not something that the RTL itself exposes functionality for, so you will have to implement it manually.
Since you are working with legacy code, I'm assuming you are working on Windows only. In which case, ParamStr() and ParamCount() parse the string returned by the Win32 API GetCommandLine() function in kernel32.dll.
So, one option is to simply hook the GetCommandLine() function itself at runtime, such as with Microsoft's Detours, or other similar library. Then your hook can return whatever string you want 1.
1: for that matter, you could just hook ParamCount() and ParamStr() instead, and make them return whatever you want.
Another option - which requires messing around with lower-level memory that you don't own, and I don't advise doing this - is to obtain a pointer to the PEB structure of the calling process. You can obtain that pointer using NTQueryInformationProcess(ProcessBasicInformation). The PEB contains a ProcessParameters field, which is a pointer to an RTL_USER_PROCESS_PARAMETERS struct, which contains the actual CommandLine string as a UNICODE_STRING struct. If your altered string is less then, or equal to, the length of the original command line string, you can just alter the content of the ProcessParameters.CommandLine in-place. Otherwise, you would have to allocate new memory to hold your altered string and then update ProcessParameters.CommandLine to point at that new memory.

Using Dart as a DSL

I am trying to use Dart to tersely define entities in an application, following the idiom of code = configuration. Since I will be defining many entities, I'd like to keep the code as trim and concise and readable as possible.
In an effort to keep boilerplate as close to 0 lines as possible, I recently wrote some code like this:
// man.dart
part of entity_component_framework;
var _man = entity('man', (entityBuilder) {
entityBuilder.add([TopHat, CrookedTeeth]);
})
// test.dart
part of entity_component_framework;
var man = EntityBuilder.entities['man']; // null, since _man wasn't ever accessed.
The entity method associates the entityBuilder passed into the function with a name ('man' in this case). var _man exists because only variable assignments can be top-level in Dart. This seems to be the most concise way possible to use Dart as a DSL.
One thing I wasn't counting on, though, is lazy initialization. If I never access _man -- and I had no intention to, since the entity function neatly stored all the relevant information I required in another data structure -- then the entity function is never run. This is a feature, not a bug.
So, what's the cleanest way of using Dart as a DSL given the lazy initialization restriction?
So, as you point out, it's a feature that Dart doesn't run any code until it's told to. So if you want something to happen, you need to do it in code that runs. Some possibilities
Put your calls to entity() inside the main() function. I assume you don't want to do that, and probably that you want people to be able to add more of these in additional files without modifying the originals.
If you're willing to incur the overhead of mirrors, which is probably not that much if they're confined to this library, use them to find all the top-level variables in that library and access them. Or define them as functions or getters. But I assume that you like the property that variables are automatically one-shot. You'd want to use a MirrorsUsed annotation.
A variation on that would be to use annotations to mark the things you want to be initialized. Though this is similar in that you'd have to iterate over the annotated things, which I think would also require mirrors.

Connecting a lua state to another one

I am using Lua to extend my C++ application. My application have some parts(ex: timer event, ui events) that can be extended by Lua, so for each part, I make a new state and load files and functions related to that part in it, so making a change to a part and reloading it wont affect the other parts.
Now I am in a situation that I need some general files to be shared among all other parts.
like for example : I am making a function for the timer events part, and there is a object defined in those general files i want to change its info in this function.
Now i am in the ui event part and I need when i access that object in the general file I want it to contain the changes that was made from the ui part.
So I thought about creating another state for those and like make an __index for the global table in the other state to search this state if they don't find some stuff in it:)) apparently I don't know how to make that.
I hope someone get what I mean and tell me how to make that?!
Lua states created with lua_newstate or lua_newstate are completely separated and cannot directly talk to each other: you need to copy data manually from one state to the other.
You can set an __index metamethod for the global table in one state to look for the data in the other one, but you'll have to do it in C or export a function to Lua that does that.

Wrapper class for thread-safe objects

I have recently played around with one demo opensource project for the basic functionality of the INDY10 TCP/IP server and stumbled upon the problem of internal multitasking implementation of INDY and its interaction with VCL components. Since there are many different topics in SO on the subject, I decided to make a simple client-server application and test some of the solutions and approaches suggested, at least the ones that I understood correctly. Below I would like to summarize and review an approach that was previously suggested on SO, and if possible listen to your expert opinion on the subject.
Problem: Encapsulation the VCL for thread-safe usage inside an indy10-based client/server application.
Description of the Development Env.:
Delphi Version: Delphi® XE2 Version 16.0
INDY Version 10.5.8.0
O.S. Windows 7 (32Bit)
As mentioned in the article ([ Is the VCL Thread-safe?]) (sorry I do not have enough reputation to post the link) special care should be taken when one wishes to use any kind of VCL components inside a multithreaded (multitasking) application. VCL is not thread safe, but can be used in a thread safe way!
The how and the why usually depend on the application at hand but one can attempt to generalize a bit and suggest some kind of general approach to this problem. First of all, as in the case of INDY10, one does not need to be explicitly parallelizing his code, i.e. create and execute multiple threads, in order to expose VCL to deadlocks and data inter dependencies.
In every sclient-server application, the server has to be able to handle multiple requests simultaneously, so naturally, INDY10 internally implements this functionality. This would mean that the INDY10 set of classes are responsible to manage the program's thread creation, execution and destruction procedures internally.
The most obvious place where our code is exposed to the inner workings of INDY10 and hence possible thread conflicts, is the IdTCPServerExecute (TIdTCPServer onExecute event) method.
Naturally, INDY10 provides classes (wrappers) that ensure thread-safe program flow, but since I did not manage to get enough explanation on their application and usage, I prefer a custom made approach.
Below I summarize a method ( the suggested technique is based on a previous comment I found in SO How to use TIdThreadSafe class from Indy10 ) that attempts (and presumably succeeds) in dealing with this problem:
The question I tackle below is: How to make a specific class "MyClass" ThreadSafe?
The main idea is to create kind of a wrapper class that encapsulates "MyClass" and queues the threads that try to access it in First-In-First-Out principle. The underlying objects that are used for synchronization are [Windows's Critical Section Objects.].
In the context of a client-server application, "MyClass" will contain all thread unsafe functionality of our server, so we will try to ensure that those procedures and functions are not executed by more than one working thread simultaneously. This naturally means loss of parallelism of our code, but since the approach is simple and seems to be , in some cases this maybe a useful approach.
Wrapper class Implementation:
constructor TThreadSafeObject<T>.Create(originalObject: T);
begin
tsObject := originalObject; // pass it already instantiated instance of MyClass
tsCriticalSection:= TCriticalSection.Create; // Critical section Object
end;
destructor TThreadSafeObject<T>.Destroy();
begin
FreeAndNil(tsObject);
FreeAndNil(tsCriticalSection);
inherited Destroy;
end;
function TThreadSafeObject<T>.Lock(): T;
begin
tsCriticalSection.Enter;
result:=tsObject;
end;
procedure TThreadSafeObject<T>.Unlock();
begin
tsCriticalSection.Leave;
end;
procedure TThreadSafeObject<T>.FreeOwnership();
begin
FreeAndNil(tsObject);
FreeAndNil(tsCriticalSection);
end;
MyClass Definition:
MyClass = class
public
procedure drawRandomBitmap(abitmap: TBitmap); //Draw Random Lines on TCanvas
function decToBin(i: LongInt): String; //convert decimal number to Bin.
procedure addLineToMemo(aLine: String; MemoFld: TMemo); // output message to TMemo
function randomColor(): TColor;
end;
Usage:
Since threads execute in order and wait for the thread which has the current ownership of the critical section to finish (tsCriticalSection.Enter; and tsCriticalSection.Leave;) it is logical that if you want to manage that ownership relay, you need one unique instance TThreadSafeObject (you can consider using the singleton pattern). so include:
tsMyclass:= TThreadSafeObject<MyClass>.Create(MyClass.Create);
in Form.Create and
tsMyclass.Destroy;
in Form.Close; Here tsMyclass is a global variable of type MyClass.
Usage:
Regarding the usage of MyClass try the following:
with tsMyclass.Lock do
try
addLineToMemo('MemoLine1', Memo1);
addLineToMemo('MemoLine2', Memo1);
addLineToMemo('MemoLine3', Memo1);
finally
// release ownership
tsMyclass.unlock;
end;
, where Memo1 is an instance of a TMemo component on the form.
With this, we are supposed to ensure that anything that happens when tsMyClass is locked
will be executed by only one thread at a time. An obvious drawback of this approach, however, is that since I have only one instance of tsMyclass, even if one thread is trying to draw for e.g. on the Canvas, while another is writing on the Memo, the first thread will have to wait for the second to finish and only then it will be able to carry out its job.
My questions here are:
Is the above suggested method correct? Am I still free of race
conditions or do I have some "loopholes" in the code, from where
data conflicts could occur?
How can one, in general, test for thread
unsafety of his/her applicaiton?
I would like to stress that the above approach is in no way my own doing. It is basically a summary of the solution found in 2. Nevertheless, I have decided to post again in an attempt to get some kind of closure on the topic or a kind of proof of validity for the suggested solution. Besides, repetition is mother of all knowledge, as they say.
With this, we are supposed to ensure that anything that happens when
tsMyClass is locked will be executed by only one thread at a time. An
obvious drawback of this approach, however, is that since I have only
one instance of tsMyclass, even if one thread is trying to draw for
e.g. on the Canvas, while another is writing on the Memo, the first
thread will have to wait for the second to finish and only then it
will be able to carry out its job.
I see one big problem here: the VCL (forms, drawing, etc...) lives on the main thread. Even if you block concurrent thread access, the updates need to be done in the context of the main thread. This is the part where you need to use Synhronize(), the big difference with a lock (Criticalsection) is that synchronized code is ran in the context of the main thread. The end result is basically the same, your threaded code is serialized and you lose the advantage of using threads in the first place.
Locking on the whole object can be much too coarse.
Imagine cases where some properties or methods are independent of others. If the lock works on a "global" level, many operations will be blocked needlessly.
From Reduce lock granularity – Concurrency optimization
So, how can we reduce lock granularity? With a short answer, by asking
for locks as less as possible. The basic idea is to use separate locks
to guard multiple independent state variables of a class, instead of
having only one lock in class scope.
First things first: You don't need to implement a LOCK for each of your objects, Delphi's done that for you with the TMonitor class:
TMonitor.Enter(WhateverObject);
try
// Your code goes here.
finally TMonitor.Leave(WhateverObject);
end;
just make sure you free the WhateverObject when your application shuts down, or else you'll run into a bug that I've opened on QC: http://qc.embarcadero.com/wc/qcmain.aspx?d=111795
Secondly, making an application multi-threading is a bit more involved. You can't just wrapp each call between Enter/Leave calls: your "locking" needs to take into account what the object does and what the access pattern is. Wrapping calls within Enter/Leave simply make sure that only one thread runs that method at any time, but race conditions are much more complex, and might arise from successive calls to your locked methods. Even those each method is locked, and only one thread ever called those methods at any given time, the state of the locked object might change between as a consequence of other thread's activity.
This kind of code would be just fine in a single-threaded application, but locking at method level is not enough when switching to multi-threaded:
if List.IndexOf(Something) = -1 then
List.Add(Something);

How best to expose a class instance in DWScript

I am putting together a built-in script capability using the excellent Pascal DWScript. I have also add my own Delphi-side class definition (TDemo) to DWScript using:
dwsUnit.ExposeRTTI( TDemo.ClassInfo )
This just works and is a great way of quickly adding properties and methods.
I also wish to add an existing instance in a similar way, so I have created my instance FDemo of type TDemo and then performed:
dwsUnit.ExposeInstanceToUnit( 'Demo', 'TDemo', FDemo );
This looks a promising routine to call but I get an AV from an uninitialised unit table. I've also looked in the unit test code of the SVN source to see the use of this function but to no avail. Can anyone point me at what I should add / change?
ExposeInstanceToUnit has to be used from within the TdwsUnit table initialization, see RTTIExposeTests/ExposeInstancesAfterInitTable for some sample code. It allows directly exposing dynamic instances.
The other approach is to use the Instances collection of a TdwsUnit component, you get design-time support, and more controls over your instances and their lifetime.
Also keep in mind you have to make sure the instances you expose will properly behave even if the script misbehaves, f.i. when the user attempts to manually destroys an instance you exposed, and that instance shouldn't be destroyed. By default ExposeRTTI will map the destructors, so you may want to restrict that by specifying eoNoFreeOnCleanup.
edit: a last approach recently added is to use the TdwsRttiConnector, which basically allows exposing and connection to anything that's reachable through RTTI. That's very lightweight in terms of code to setup, but the downside is you don't get any form of compile-time checks.

Resources