-
Content Count
914 -
Joined
-
Last visited
-
Days Won
55
Everything posted by pyscripter
-
How can globals be shared amongst multiple modules?
pyscripter replied to RSG's topic in Python4Delphi
Could you post a sample project that demonstrates the issue? -
Firstly, let me say that my work on SynEdit has moved back to pyscripter/SynEdit for reasons explained here. The newest enhancement to SynEdit is accessibility support. Now, SynEdit fully supports screen readers such as Windows Narrator and NVDA. The support is much better than, for instance, in Visual Studio Code. The implementation is not based on the older Microsoft Active Accessibility (MSAA), but on the newer Microsoft UI Automation. Microsoft UI Automation has been around since 2005 and is available to all Windows versions, since Windows XP. In addition to making applications accessible, it can also be used by automated UI testing tools. Despite been available for almost 20 years, Delphi does not provide the relevant header translations (See RSP-41898), which complicated the implementation. I also could not find any other complete Delphi implementation of UI automation. So, the SynEdit implementation may serve as a guide to how to implement UI Automation in other controls. Further details can be found here.
-
How can globals be shared amongst multiple modules?
pyscripter replied to RSG's topic in Python4Delphi
If you want to preserve globals in script execution you need to use the ExecString(s) overload with the locals, globals parameters. -
Handling Python indented blocks with ExecString()
pyscripter replied to RSG's topic in Python4Delphi
Python code needs to be properly indented (see for instance Python Indentation (w3schools.com)). Otherwise you will get the IndentationError you show above. If you want to built your own interpreter, a good starting point is the InteractiveInterpeter class of the code module. The runsource method will tell you whether the input is incomplete and more input is required. -
How can globals be shared amongst multiple modules?
pyscripter replied to RSG's topic in Python4Delphi
I am not sure what the issue you are trying to solve is. You can have the statement: from oct2py import Oct2Py or just import oct2py within different python modules or functions. It does not result in the module being reimported. If it has been already imported it just uses the already imported one and there is no speed penalty. The same applies to the VarPyth Import statement. -
In an earlier thread I presented an Interface-based access to native Windows (Direct2D) SVG support for Delphi applications. This has now been integrated into the SVGIconImageList components by @Carlo Barazzetta. Carlo is a kind of master of ImageLists (among other things). Have a look at his IconFontsImageList for instance. His SVGIconImageList component was based on the work of Martin Walter who must be a great programmer. His SVG component covered almost every SVG element and was well structured and cleanly written. There were numerous bugs and issues though, which, to a large extent, were fixed over the last few weeks and the code was refactored and optimized. Finally, @Vincent Parrett contributed a virtual version of the Image List, mirroring Delphi's VirtualImageList. So in its current form the component features: An SVGImageCollection component that inherits from Delphi's CustomImageCollection and thus is compatible with VirtualImageList A choice of SVG engines: the pascal one based on Martin's work which is using GDI+ and the native Windows one which is using Direct2D. Other SVG engines can be plugged-in with minimum effort. Excellent design support with a nice and effective SVGImageCollection editor developed by Carlo and the built-in VirtualImageList editor. Support for changing the opacity and color of the SVGs including using GrayScale. If you adopt Material Design for example and you use VCL styles, you can adjust the icon color to the style. Compatibility with older Delphi versions going back to XE6. It is free and open-source Svgs are vastly superior to bitmaps because they are typically tiny text files and scale perfectly. So, you do not need to ship with your application multiple resolutions of your images to match the DPI of the monitors. And there is a vast number of free SVGs to cover most needs. IMHO the combination of SVGImageCollection with Delphi's VirtualImageList is the best available solution (commercial ones included) for building DPI-aware Windows applications. Give it a try.
-
Calling python scripts. Returning python output.
pyscripter replied to marcovth's topic in Python4Delphi
See Demo1. -
Demo32 demonstrates how to use PyArg_ParseTupleAndKeywords.
-
Not so simple: python - Overriding __setattr__ at runtime - Stack Overflow
-
function TPyPoint.SetAttr(key : PAnsiChar; value : PPyObject) : Integer is called whenever a property is set (e.g. spam.myPoint.x = 10). So you can take an action when the object is modified. However you are not notified when spam.myPoint is assigned a value. To do what you would have to override the __setattr__ on the module, but this is too complicated.
-
See multithreading - Python threading interrupt sleep - Stack Overflow for alternatives to sleep that can be interrupted.
-
from io import StringIO import sys old_stderr = sys.stderr sys.stderr = mystderr = StringIO() # examine mystderr.getvalue()
-
I wrote the code without testing, just to give you the idea. Good that you solved the problem. Also instead of MainModule.builtins._input_prompt you can use BuiltinModule._input_prompt. And the following would do. No need to convert to AnsiString and back. procedure TForm1.PythonInputOutput1ReceiveUniData(Sender: TObject; var Data: string); begin InputQuery( 'Query from Python', BuiltinModule._input_prompt, Data); end;
-
Run a script like this: import builtins def myinput(prompt): builtins._input_prompt = prompt builtins._input(prompt) builtins._input = builtins.input builtins.input = myinput Then the prompt will be stored in builtins._input_prompt
-
Dictionaries are downloaded via Windows Language preferences. You just select the language as in the demo.
-
The KeyboardInterrupt is the correct way to terminate a thread from the main thread. This is because print statement executes without clearing the KeyboardInterrupt exception. You need to trap the KeyboardInterrupt exception either in Python or Delphi code. You can also add to your PythonInputOutput1SendUniData with GetPythonEngine do if PyErr_Occurred <> nil then begin PyErr_Clear; Exit; end;
-
How are you exiting the thread? Are you raising a KeyboardInterrupt as in demo 33? Then why are you surprised that an exception is raised, when the print statement executes. You can modify your script as follows (not tested): while True: try: time.sleep(0.1) print(datetime.now()) except KeyboardInterrupt: break or handle the exception in your Delphi code
-
You are producing output at a high speed from a thread. You need to buffer the output in a way similar to that in python4delphi/Unit1.pas at master · pyscripter/python4delphi (github.com).
-
Yes indeed! P4D makes it quite easy. The TStrings wrapper does that for instance.
-
See Passing a python object to a delphi function parameter - Python4Delphi - Delphi-PRAXiS [en] (delphipraxis.net)
-
Passing a python object to a delphi function parameter
pyscripter replied to iqrf's topic in Python4Delphi
No. You should try to understand the rules behind reference counting. (e.g. Reference Counting in Python (tripod.com)) Note that PyBytes_FromStringAndSize returns a new reference, so there is no need to increment the count. Adjust(Self) is needed when you need to access the Delphi object properties or methods. -
Passing a python object to a delphi function parameter
pyscripter replied to iqrf's topic in Python4Delphi
On the Delphi side you can use PyArg_ParseTuple to get the pointer to the python object. Then you can either: use the python API to call the desired method on the python object or wrap the python object into a custom variant (VarPythonCreate in the VarPyth unit) and call the method in a high-level way. See tutorials and demos on VarPyth for details -
P4D installation error in Delphi 11.3
pyscripter replied to Alexander-R-Bio's topic in Python4Delphi
Try the sources in pyscripter/python4delphi: Free components that wrap up Python into Delphi and Lazarus (FPC) (github.com) and follow the installation instructions. You should report the GetIt issue to the fork Embarcadero/python4delphi: Fork of P4D adding FireMonkey wrapper and Android support (github.com) which is used to create the GetIt package. -
Best Practice Question: Bidirectional EXE-to-EXE communication
pyscripter replied to Alexander Halser's topic in RTL and Delphi Object Pascal
The IPC unit based on named pipes created by Russell Libby in 2003 and updated by @FPiette is worth checking. Blog article: Behind the connection: Inter Process Communication Using Pipes (francois-piette.blogspot.com) Source code: OverByte - Blog Source Code Named pipes in overlapped mode are super efficient and faster than sockets. See Synchronous and Overlapped Pipe I/O - Win32 apps | Microsoft Learn. See also I/O Completion Ports - Win32 apps | Microsoft Learn. I have contributed such a solution to the python library RPyC and it beats the socket based IPC by a large margin. The downside is that it is Windows only. -
In case this of use to anyone: Quite often you find a bug in Delphi RTL and you come up with a fix. Patching involves replacing the RTL procedure with a new patched one. To do that you can use your favorite patching routine or library (I use Detours), but you need the address of the original function/method. a) Patching a non-virtual public method This is quite straight-forward: type TMethodType = procedure ... of object function GetAddress: Pointer; var MethodPtr : TMethodType; begin MethodPtr := TRTLClass(nil).PublicMethod; Result := TMethod(MethodPtr).Code; end; Note the type cast TRTLClass(nil). b) Patching a virtual public method If for example PublicMethod is virtual the above type cast TRTLClass(nil) with result in access violation, since to resolve the virtual method you need to access Self which is nil. You could create a class instance and use that instead of TRTLClass(nil), but apart from not being elegant, in some cases this has side-effects (for example it may require a valid windows handle). The trick is described in this Stackoverflow question. function GetAddress: Pointer; var VMT : NativeInt; MethodPtr: TMethodType; begin VMT := NativeInt(TRTLClass); MethodPtr := TRTLClass(@VMT).PublicMethod; Result := TMethod(MethodPtr).Code; end; This is based on two facts. A class is a pointer to the Virtual Method table (VMT) and an Object structure has as the first field a pointer to the VMT of its class. c) Patching a private virtual method The trick this time involves using a class helper to access the private method of the TRTLClass type TPrivateMethodType = procedure ... of object; TRTLClassHookFix = class helper for TRTLCLass function GetPriveMethodAddr: Pointer; end; function TRTLClassHookFix.GetPriveMethodAddr: Pointer; var VMT : NativeInt; MethodPtr: TPrivateMethodType; begin // Adjust Self to point to the VMT VMT := NativeInt(TRTLCLass); Self := TRTLCLass(@VMT); with Self do MethodPtr := PrivateMethod; Result := TMethod(MethodPtr).Code; end; That's it.