Jump to content

pyscripter

Members
  • Content Count

    974
  • Joined

  • Last visited

  • Days Won

    61

Posts posted by pyscripter


  1. 2 hours ago, BennieC said:

    @pyscripter

    I have used your structure but still Delphi insist on giving me strings instead of floating point values.

    image.png.b6cae72d144f79f4288f7f6bc2646a68.png

    Can I somehow force the variant conversion to take this as a float?  I have tried to assign the variant to single variable but have no luck.

    Regards

     

    Variants are converted to strings when shown in the debugger.  It does not mean that they contain strings.


  2. 2 hours ago, BennieC said:

    Value: (array([[0.09, 0.03, 0.34...0.]]. dtype=float32), array([[0.06, 0.05, 0.67...0.]]. dtype=float32))

    Currently this is just returned as a value with name layerOutputs, but Delphi sees this as a character string

    No it does not.   You get a tuple containing arrays of floating type values.   Are you using VarPyth? Is layerOutputs a Variant?

    If yes then you can use:

     

    var arr:Variant := layerOutputs.GetItem(0);  // the first item of the tupple (array).
    var value:Variant := arr.GetItem(0);  //the first floating value of the array

     


  3. 6 minutes ago, Vincent Parrett said:

    If that were the case, then you wouln't need to change anything at all in SynEdit - but you do as it cannot see SetAdditionalPCREOptions.

    The issue was in the following:

     

    procedure TRegExHelper.AddRawOptions(PCREOptions: Integer);
    begin
      with Self do FRegEx.SetAdditionalPCREOptions (PCREOptions);
    end;

    FRegEx is defined in System.RegularExpressions and the nearest helper was in that unit.

     

    By the way the issue is now fixed.  Thanks for reporting it.

    • Like 2

  4. 25 minutes ago, Vincent Parrett said:

    The one that embarcadero created will be used first, the synedit one will be ignored. Which helper is used is dependant on where they are decleared, since embarcadero declared theirs closest to the actual class declaration theirs will be seen first rather than the one on synedit. 

    Actually it is the other way round.   From the docs:

     

    Quote

    You can define and associate multiple helpers with a single type. However, only zero or one helper applies in any specific location in source code. The helper defined in the nearest scope will apply. Class or record helper scope is determined in the normal Delphi fashion (for example, right to left in the unit's uses clause).

    but "nearest scope" means closer to where the variable is declared.

     

    Just to prove:

     

    Project File:

    program Project1;
    
    {$APPTYPE CONSOLE}
    
    {$R *.res}
    
    uses
      System.SysUtils,
      Unit1 in 'Unit1.pas';
    
    type
      MyRecHelper2 = record helper for MyRec
        procedure SayHi;
      end;
    
    { MyClassHelper1 }
    
    procedure MyRecHelper2.SayHi;
    begin
      WriteLn('Hello!');
    end;
    
    var
      Rec: MyRec;
    
    begin
      Rec.SayHi;
      ReadLn;
    end.

    Unit 1

     

    unit Unit1;
    
    interface
    
    type
    
      MyRec = record
    
      end;
    
      MyRecHelper1 = record helper for MyRec
        procedure SayHi;
      end;
    
    implementation
    
    { MyClassHelper1 }
    
    procedure MyRecHelper1.SayHi;
    begin
      WriteLn('Hi!');
    end;
    
    end.

    Output:

    Hello!

     


  5. 11 minutes ago, Vincent Parrett said:

    the best option would be to change SetAdditionalPCREOptions to AddRawOptions - then it will compile in all supported versions.

    What happens then in Delphi 11.2?   Which record helper will be active?  I thought you are not allowed to have two helpers for the same class in the same scope?


  6. I am having issues upgrading to 11.2.   I run the Web Installer keeping the registry options.  It appears to be going smoothly , uninstalling the previous version, then showing a message "Installing Main Application files" and in a few seconds it stops with a message "installation finished".

     

    I can see the application files in the Programs directrory, it even installs a shortcut on the desktop.  But at the end of the installation I can see a running process bds.exe, that does nothing.  If I end the process and try to run Rad Studio from the shortcut the bds.exe process starts but nothing happens.

     

    I remember that with previous version upgrades it would ask me for personalities and download tons of stuff from the cloud.   This time nothing of the sort.

     

    Any clues?

     

    Update:  The issue was related to addins.   After removing the references to Beyond Compare, Parnassus and Gexperts, bds.exe started and allowed me to select platforms.   It is now downloading and installing OK.  And it works well.

     

     


  7. This is a code fragment that shows you how to convert python strings to Delphi strings with PyArg_ParseTuple


     

    function ShowMessage_Wrapper(pself, args: PPyObject): PPyObject; cdecl;
    var
      LMsg: PAnsiChar;
    begin
      with GetPythonEngine do
      begin
        if PyArg_ParseTuple(args, 's:ShowMessage', @LMsg) <> 0 then
        begin
          ShowMessage(Utf8ToString(LMsg));
          Result := GetPythonEngine.ReturnNone;
        end else
          Result := nil;
      end;
    end;

     

    Also have a look at the PyArg_ParseTuple documentation.

     

     

    Using such methods is the low level approach to exposing Delphi code to python.    Please have a look at WrapDelphi demos and tutorials for a high-level approach that that does not require you to use PyArg_ParseTuple or worry about reference counting and the like.  

    • Like 2

  8. You can use LockUndo to disable Undo altogether.

    LockUndo/UnlockUndo is also useful when you read a file or initially setup a text buffer.  If the Undo buffer is not empty then you would want to call ClearUndo before or after.


  9. Assuming you are using the Turbopack Synedit:

     

    Changes to the text buffer are undoable.   So just calling Delete does not clear all related memory.    You need to do one of:

    • call ClearUndo every now and then to release the undo/redo memory.
    • Set MaxUndo to some number to limit the undoable actions.  The default is 0 (unlimited undo/redo).
    • call LockUndo/Unlock undo to prevent actions being added to the undo/redo stack (the most efficient).

    If you still get a memory overflow then this is a bug that you should report.

     

    • Like 1

  10. I had a similar issue.   If I remember well, setting the ParentBackground property to true for all controls helped, although I see in the previous thread that @Uwe Raabe claimed the opposite.

     

    There was such an issue https://quality.embarcadero.com/browse/RSP-31158 that is supposed to be fixed in D11.   See also the related issues to this one.

     

    See also TStyleManager.UseParentPaintBuffers introduced in D11.   I have not tried it and there is limited documentation.

    • Thanks 1

  11. In using delphivcl.pyd  the user can attach an arbitrary python method as an event handler to any vcl component at runtime.   The event handler needs to be created on-the-fly, since you do not know in advance what python method will attach to which events.   TMethodImplementation can do just that.  Create an event handler of the right type when it is need.  In this use case the callback would translate the Args to their python equivalents and call the python code.

     

    The callback can be an anonymous method, but this is not important.  The important thing is that the event handler needs to be created at runtime and not at compile time.  Currently  python4delphi needs to provide helper classes for each event type (TNotifyEventHandler for TNotifyEvent etc.).  All this code can go away and have just one generic implementation of event handling that can deal with any kind of event.

     

    For example in the code below:

     

    class MyForm(Form):
        def __init__(self, owner):
            self.timer = Timer(self)
            self.timer.Interval = 10
            self.timer.OnTimer = self.__on_timer
            self.timer.Enabled = True
    
        def __on_timer(self, sender):
            self.CheckBox1.Enabled = True

    when self.timer.OnTimer = self.__on_timer is executed an event handler needs to be attached to the OnTimer event of a Delphi timer object that will run the python method.

     


  12. 1 hour ago, Dave Novo said:

    While technically this seems cool, why is this particularly useful? I see that I can create an event handler without an explicit object that will implement the event handler method. Why would I need to do this?

     

    Did you read my first post?  It answers your question providing some use cases.  Spring4d also uses this for supporting multicast events.


  13. Here is an example of making an event handler on the fly using spring4d, TMethodImplementation and a callback routine, in case anyone has a use for it.

     

    program MethodImplementationTest2;
    {$APPTYPE CONSOLE}
    {$R *.res}
    
    uses
      System.SysUtils,
      System.TypInfo,
      System.Rtti,
      Spring;
    
    type
      TSimpleEvent = function(I: Integer): Integer of object;
    
      TTestClass = class
      private
        fEvent: TSimpleEvent;
      published
        property Event: TSimpleEvent read fEvent write fEvent;
      end;
    
    procedure ImplCallback(UserData: Pointer; const Args: TArray<TValue>;
        out Result: TValue);
    begin
      WriteLn('From Implementation');
      WriteLn(Args[0].AsObject.ClassName);
      Result := Args[1].AsInteger * 2;
    end;
    
    begin
      ReportMemoryLeaksOnShutdown := True;
      var TestObj := Shared.Make(TTestClass.Create)();
      try
        var RTTIContext := TRttiContext.Create;
        var RTTIType := RTTIContext.GetType(TypeInfo(TTestClass));
        var RTTIMethodType := RTTIType.GetProperty('Event').PropertyType;
    
        var MethodImplementation := (RTTIMethodType as TRttiInvokableType).CreateImplementation(nil, ImplCallback);
        var Method: TMethod;
        Method.Code := MethodImplementation.CodeAddress;
        Method.Data := TestObj;
        SetMethodProp(TestObj, 'Event', Method);
    
        WriteLn(TestObj.Event(2));
        MethodImplementation.Free;
      except
        on E: Exception do
          Writeln(E.ClassName, ': ', E.Message);
      end;
      ReadLn;
    end.

    Output:

     

    From Implementation
    TTestClass
    4

     


  14. System.Rtti contains a lesser known, but powerful class TMethodImplementation, which is basically hidden and used in TVirtualMethodInterceptor.  Outside this use, it cannot be created directly and it can only be accessed by TRttiMethod.CreateImplementation.   

     

    I recently discovered that Spring4d extends its use through a helper for TRttiInvokableType, so it can be used with standalone procedures and functions as well as with events.  Here is a small console app showing how it can be used:

     

    program MethodImplementationTest;
    {$APPTYPE CONSOLE}
    {$R *.res}
    
    uses
      System.SysUtils,
      System.TypInfo,
      System.Rtti,
      Spring;
    
    type
      TSimpleProc = function(I: Integer): Integer;
    
    procedure ImplCallback(UserData: Pointer; const Args: TArray<TValue>;
        out Result: TValue);
    begin
      WriteLn('From Implementation');
      Result := Args[0].AsInteger * 2;
    end;
    
    var
      Proc: TSimpleProc;
    begin
      ReportMemoryLeaksOnShutdown := True;
      try
        var RTTIContext := TRttiContext.Create;
        var RTTIType := RTTIContext.GetType(TypeInfo(TSimpleProc));
        var ProcImplementation := (RTTIType as TRttiInvokableType).CreateImplementation(nil, ImplCallback);
    
        Proc := TSimpleProc(ProcImplementation.CodeAddress);
    
        WriteLn(Proc(2));
        ProcImplementation.Free;
      except
        on E: Exception do
          Writeln(E.ClassName, ': ', E.Message);
      end;
      ReadLn;
    end.

    Output:

    From Implementation
    4
    

    Simple and easy.  Spring4D is full of gems.  I wish the above functionality was part of the standard library.

     

    I can think of many uses:

    • Python4Delphi contains a unit MethodCallback which uses complex assembly to convert methods into stubs that can be used with external C libraries.  It could be rewritten using TMethodImplementation, without assembly code.
    •  Also in Python4Delphi, the implementation of Delphi events using python code could be very much simplified and generalized using TMethodImplementation.  You can create Delphi functions, procedures and methods, event handlers on the fly that are implemented by python code.
    • Similarly functionality can be provided with other scripting languages.

     

    • Like 2

  15. Just to clarify.   

     

    a)  No memory leakage happens if your timer routine is:

     

        def __on_timer(self, sender):
            pass

     

    b)  The increase in memory usage increases indefinitely when self.CheckBox1.Enabled = True is called inside the timer routine.

     

    c) Could this be tracemalloc overhead?   (the memory traces take memory space).  For example does the memory gets released with 

    tracemalloc.clear_traces()  (tracemalloc — Trace memory allocations — Python 3.10.5 documentation)

     

    d) Do you see Windows memory allocated to the process increasing without tracemalloc

×