Jump to content

JGMS

Members
  • Content Count

    49
  • Joined

  • Last visited

Posts posted by JGMS


  1. The three possible ways in creating the threads give totally different memory leakage messages when closing the application.
    But none of them successfully mirrors the pictures, nor do they show error messages.

    1) TPyThread.Create(emNewInterpreter) gave no memory leak messages.
    2) TPyThread.Create(emNewInterpreterOwnGIL) results 17 out 25 files memory leaks.

    3)TPyThread.Create(emNewInterpreterO1886347803_Schermafbeelding2025-06-15152136.png.4cb945f2a8ad13b74a98a96fa498b500.pngwnGIL) 25 memory, and different to the previous one1954616827_Schermafbeelding2025-06-15151841.png.04433094fbaae25d1aa74df520481bfb.png

    I started off with demo 36 and got it running, but experienced the same  'c0000005 ACCESS_VIOLATION' initially, until I started playing with the sleep function.
    The demo appears to need the sleep anyway, with or without the try ..finally addition, you mentioned.
    I tryed to read the documentation in the link, but failed to see info about whether or not PIL is supported. I begin to believe that that is indeed the problem that I face. That would be all too pity.


  2. After studying Demo 36 I made a unit to use the concept in a VCL program to process a bunch of jpg pictures, in parallel mode. I used exactly the same code, except of course for the script.


    It failed in the procedure "DestroyEngine" when freeing the engine: 'Project .... raised exception class $C0000005 with message 'c0000005 ACCESS_VIOLATION'".
    I suspect that the Event.Waitfor command does not wait until the saving of the jpg's is finished. Or perhaps, file processing isn't possible at all in this way.
    Anyway, I could not find a long enough sleeping time as set before destroying the PythonEngine. 

    I also tried to run the program using "emNewInterpreter" instead of "emNewInterpreterOwnGIL". This does not give errors when freeing the engine, but the script neither runs;

    The Pythoncode that is in the script runs perfect in PyScripter, but not in the modified Demo 36.

    Here is the function that should do the job:

    Function RunParallel(MapBron, MapDoel : String; InitScript : String) : Boolean;
    var
      I, N: Integer;
      InTijdlijnStr : String;
    begin
      Result := True;
      InArray := TDirectory.GetFiles(MapBron,'*' + ExtensieFotoBestand);
      N := 25;//length(Inarray); // limit for testing
      IF N = 0 then exit;
      try
        CreatePyEngine;
        try
          Event := TCountdownEvent.Create(N);
          // 'Subinterpreter with own GIL:
          for I := 1 to N do
          begin
            Var Doel : String := IncludeTrailingPathDelimiter(B2F(MapDoel)) + ExtractFilename(InArray[I-1]);
            Script := InitScript + 'mirror("' + B2F(InArray[I-1]) + '")';
            TPyThread.Create(emNewInterpreter); // TPyThread.Create(emNewInterpreterOwnGIL);
          end;
          Event.WaitFor;
          Event.Free;
        finally
          Sleep(3000);  // allow some time for the threads to terminate
          DestroyEngine;
        end;
      except
        on E: Exception do
        Result := False;
      end;
    end;


     

    I used a simple test script, as shown below. It is rerun in a loop. The final line is added in the loop, as seen in the above function.

    import piexif
    from PIL import Image
    
    def mirror(input_path):
       img = Image.open(input_path)
       try:
         exif_dict = piexif.load(img.info["exif"])
       except:
         exif_OK = False
       else:
         exif_OK = True
       rot_img = img.transpose(method=Image.FLIP_LEFT_RIGHT)
       w, h = rot_img.size
       if exif_OK:
         exif_dict["0th"][piexif.ImageIFD.XResolution] = (w, 1)
         exif_dict["0th"][piexif.ImageIFD.YResolution] = (h, 1)
         try:
           exif_bytes = piexif.dump(exif_dict)
         except:
           rot_img.close()
           return
         rot_img.save(input_path, "jpeg", exif=exif_bytes, quality=95)
       else:
         rot_img.save(input_path, "jpeg", quality=95)
       rot_img.close()
       
    mirror("F:/Eline/Marie/20150720 103259_NIKON.JPG")   <=== added in the loop

    Would you please give me some hints on how to proceed.
    Many thanks ahead.

    Jan


  3. I want to run python functions in the background, for example like so:

    MI_CopyrightAddition.Enabled := false;
    TTask.Run( Procedure
    begin
     PyForm.Add_Copyright_Using_Python(FotoSerie,CopyRightTeken + String(CopyRightTekst), False);
     TThread.Synchronize(nil, procedure
       begin
         MI_CopyrightAddition.Enabled := TRUE;
       end);
    end);



    "PyForm.Add_Copyright_Using_Python" is a correctly working Python function, running normally in the main Thread.

    But in the above scheme it crashes:
    "Project .... raised exception class $C0000005 with message 'c0000005 ACCESS_VIOLATION'."

    Is there a way to get this working?

    Many thanks for your time.


  4. Thank you very much indeed @pyscripter!
    You put me on the right track. The modulename had to be removed too, I understood from your example.
    Now the function works like a charm:


     

       PythonModule1.SetVarFromVariant( 'Varr', Arr );
    
        Mem := TStringList.Create;
        With Mem DO
        begin
          Add('from deep_translator import GoogleTranslator');
          Add('from delphi_module import Varr');
          Add('taalcode = "' + taalcode +'"');
          Add('taalnr = ' + I2S(TaalNr) );
          Add('for j in range(len(Varr)):');
          Add('  translated = GoogleTranslator(source="nl", target=taalcode).translate(text=Varr[j][0])' );
          Add('  Varr[j][taalnr]=translated');
        end;
         TRY
     
        GetPythonEngine.Execstring(UTF8Encode(mem.text));
        Mem.Free;
    
        Arr :=  PythonModule1.GetVarAsVariant( 'Varr' ); // VAR parameter returned to calling function.
        

    I am very happy now. Many thanks again and best wishes.
     


  5. I studied Demo 17 to use it in my application.
    The following routine is what I made from it:

    Function TPyForm.VertaalMetPython(Var Arr : Variant; TaalCode : String; TaalNr : integer) : Boolean;
     VAR
       Mem   : TStringList;
       
      begin
        Result := False;
    
       // Arr is created upfront with: Arr   := VarArrayCreate([0, FDQ_comps.RecordCount-1, 0, 5], VarVariant),
       // and populated with variant data in a for loop: ... VarArrayPut(Arr, FDQ_comps.Fieldbyname('nederlands').AsVariant, [I, 0]) ...;
       // PythonModule1.Engine     := PythonEngine1;
       // PythonModule1.ModuleName := 'Vertaal';
    
       PythonModule1.SetVarFromVariant( 'PArr', Arr );
    
       TRY
        Mem := TStringList.Create;
        With Mem DO
        begin
          Add('from deep_translator import GoogleTranslator');
    
          Add('taalcode = "' + taalcode +'"');
          Add('taalnr = ' + TaalNr.toString );
          Add('for j in range(len(Vertaal.PArr)):');
          Add('  translated = GoogleTranslator(source="nl", target=taalcode).translate(text= Vertaal.PArr[j, 0])' ); 
          Add('  Vertaal.PArr[j, taalnr] = translated');
        end;
         TRY
           PythonEngine1.ExecString( ansiString( Mem.text ) );
           Arr :=  PythonModule1.GetVarAsVariant( 'PArr' );
           Result := True;
         Except
           Result := False;
         END;
         FINALLY
           Mem.Free;
         END;
      end;

     

    The input array for Python is populated correctly with data, but Python doesn't give any sign of action. The array is returned empty and the Result value is set to True.

     

    What do I wrong? Please help.

     


  6. Thank you @Serge_G and @sjordi for taking time to answer.
     

    Initially I had FMX installed by using the installer V1.77 that comes with the updates that I got from the original developer (I bought a lifetime version a couple of years ago). It always ran perfect, except for this time.

    Because of the error I subsequently installed it via GetIT (V1.76), but this yielded the same error.
    I quess things will get better after a fresh installation of the latest update to Delphi version 12.1.

    I will keep you informed.

     


    I


  7. Quote

    I have installed FmxLinux, got the PaServer up and running (D12 in Windows11, WSL2, Ubuntu22.04) and added and selected the LinuxPlatform in a new, multi-device, blank application: a form with a single button.

    In the project file (shown below) the problem is already hinted, showing:  'E2212: Package unit "FMX.Forms" cannot appear in contains or uses clauses'.

    FireMonkey applications for Windows run fine, so FMX package units cannot be missing.

    What can be wrong?

     

    
    program Project1;
    
    uses
      System.StartUpCopy,
      FMX.Forms, <<== design-time error hint 'E2212: Package unit "FMX.Forms" cannot appear in contains or uses clauses'
      Unit1 in 'Unit1.pas' {Form1};
    
    {$R *.res}
    
    begin
      Application.Initialize;
      Application.CreateForm(TForm1, Form1);
      Application.Run;
    end.
    
    var
      Form1: TForm1;
    
    implementation
    
    {$R *.fmx}
    
    end.

     

     


  8. When I create an FMX application with a StringGrid and a BindNavigator with an Onclick event, the latter sets TBindNavigatebutton as parameter rather than TNavigateButton.
    The former comes from the unit Fmx.Bind.Navigator and the latter from Data.Bind.Controls.

    This leaves the question: is there a way to let the compiler accept both parameters?


  9. image.thumb.png.db926739f827a6c155a3d09d90414f7c.png

    image.thumb.png.150c8a5e57408f83143f7ea8d1d47cfc.png

    These are the error messages I got. In common: '...has an incompatible parameter list....

    There are a number of TBindnavigators on the form connected to TStringGrids in an FMX 32 bits Windows application.

     

    The events that are connected to the BindNavigators from within the Object Inspector are defined by

      procedure TForm1.BindNavigatorBeforeAction(Sender: TObject;  Button: TNavigateButton);

    and

      procedure TForm1.BindNavigatorClick(Sender: TObject;  Button: TNavigateButton);


    If I'd click 'Yes' I will loose the LiveBindings connections. I don't even want to think of that!


  10. Thank you @Uwe Raabe 

    I preceded the respective constants in the code with 'TFDCommandKind." to overcome this problem.
    I am surprised that the Delphi 12 requires the user to make code adjustments due to changes in the compiler. This is so unlike Delphi!
    Another surpise that I face a problem due to changes in the BindNavigatorBeforeAction and BindNavigatorClick events: they fail because their parameters (Sender asTobject;  Button: TNavigateButton)  are no longer accepted!

    In Delphi 11.3 my code runs flawless!

    Might I ask whether you know what to do about this?

    May thanks, Jan


  11. Integer constants as defined in "TFDPhysCommandKind" in unit 'FireDAC.Phys.Intf' in Delphi 11.3 and below, appear to be missing in Delphi 12.

     

    TFDPhysCommandKind = (skUnknown, skSelect, skSelectForLock, skSelectForUnLock,
        skDelete, skInsert, skMerge, skUpdate, skCreate, skAlter, skDrop, skStoredProc,
        skStoredProcWithCrs, skStoredProcNoCrs, skExecute, skStartTransaction,
        skCommit, skRollback, skSet, skSetSchema, skOther, skNotResolved);

    Does anybody know what has happened to them? Any idea where to find them?
    Thanks ahead.


  12. The very day after my first post PowerPDF was available via GetIt.
    I removed the GitHub version and re-installed it through GetIt.

    However, the same "Class Arial not found" message pops up when trying to drop a TPrPage component on a form.

    Arial is a standard font and cannot be removed nor reinstalled. Moreover, it is not missing.

    Hence it does not seem te be a Windows 11 issue, but rather something wrong in PowerPDF.

    Can anyone help me with some hints? Please...


  13. I have installed PowerPDF in Delphi 12 via GitHub. The master package in Git seems to be made ready for Delphi12 (there is an 11AndAbove subdir).

    In previous Delphi versions I used to install PowerPDF via GetIt, but the package still is not available. After about 3 months I can no longer wait.

     

    Anyway, it looks like the installation was a success: all controls are in place, and I can drop a TPrReport component on a form.

    However, the next step, i.e. to drop a TPrPage, fails, showing the "Class Arial not found" message.

    Since a TPrPage is the container for all other PowerPDF controls, the package is unusable.

     

    I have no idea how to get it to work. Do you?
    I very much appreciate your help or hints.

     


  14. I have found the solution to get the original posted code to work just fine, by adding 1 line right before the return in ProcessImage:

     

    Add('  new_im.format = "JPEG"');

    Very simple, in hindsight. Any way, I learned a lot.
    However, I did not find a way to delete or update the 'miniproject' files, as yet.


  15. Thank you @pyscripter
    .
    The  code line "if PyBytes_AsStringAndSize(presult, P, Len) < 0 then" results the Delphi error "Project ... raised exception class $C0000005 with message 'c0000005 ACCESS_VIOLATION'.", since "presult" is an empty Pansichar.

    GetPythonEngine.CheckError results "Runtime error 201 at ...".

     

    I will prepare a minimal project later today, and will study demo 35 as well.

×