Jump to content

iqrf

Members
  • Content Count

    44
  • Joined

  • Last visited

Community Reputation

3 Neutral

Technical Information

  • Delphi-Version
    Delphi 11 Alexandria

Recent Profile Visitors

1081 profile views
  1. Hi, it's a little crazy, but it works. property update_state: PPyObject read GetUpdateState; function TServerRepo.GetUpdateState: PPyObject; begin with GetPythonEngine do begin result := ExtractPythonObjectFrom(MainModule.RepositoryState.uExpired); Py_IncRef(result); end; end; I achieved this by modifying WrapDelphi.pas Is it a correct solution? function TValueToPyObject(const Value: TValue; DelphiWrapper: TPyDelphiWrapper; out ErrMsg: string): PPyObject; begin if Value.IsEmpty then Result := GetPythonEngine.ReturnNone else case Value.Kind of tkClass: Result := DelphiWrapper.Wrap(Value.AsObject); tkClassRef: Result := DelphiWrapper.WrapClass(Value.AsClass); tkInterface: Result := DelphiWrapper.WrapInterface(Value); tkRecord{$IFDEF MANAGED_RECORD},tkMRecord{$ENDIF}: Result := DelphiWrapper.WrapRecord(Value); tkArray, tkDynArray: Result := DynArrayToPython(Value, DelphiWrapper, ErrMsg); // Add -> tkPointer: begin if Value.IsType<PPyObject> then Result := PPyObject(Value.AsType<Pointer>) else begin ErrMsg := rs_ErrValueToPython; Result := nil; end; end; // <- Add else Result := SimpleValueToPython(Value, ErrMsg); end; end; TServerRepo = class(TPersistent) private function GetAPIVersion: Integer; function GetUpdateState: PPyObject; function GetLastDownload: TDateTime; public constructor Create(OnlineStatus: Boolean); property api_version: Integer read GetAPIVersion; property update_state: PPyObject read GetUpdateState; property last_download: TDateTime read GetLastDownload; end; TPythonRepositorySettings = class(TPersistent) private FOfflineStatus: TServerRepo; public constructor Create; destructor Destroy; override; property online_status: TServerRepo read FOnlineStatus; end; TPyServerRepo = class(TPyDelphiPersistent) constructor CreateWith(PythonType: TPythonType; args, kwds: PPyObject); override; function Repr: PPyObject; override; class function DelphiObjectClass : TClass; override; end; TPyRepositorySettings = class(TPyDelphiPersistent) constructor CreateWith(PythonType: TPythonType; args, kwds: PPyObject); override; function Repr: PPyObject; override; class function DelphiObjectClass : TClass; override; end; .... procedure TPython.OnDelphiWrapperInitialization(Sender: TObject); begin FPythonWrapper.RegisterDelphiWrapper(TPyServerRepo); FPythonWrapper.RegisterDelphiWrapper(TPyRepositorySettings); end; ... repositorySettings := TPythonRepositorySettings.Create; prepositorySettings := FPythonWrapper.Wrap(repositorySettings, soOwned); FPythonModule_Repository.SetVar('settings', prepositorySettings); FEngine.Py_DecRef(prepositorySettings); @unique class RepositoryState(Enum): uActual = 0 uExpired = 1 uNonActual = 2 from ide import repository as repo from repository import settings as repoSet update_state = repoSet.local_cache.update_state print(update_state) print(type(update_state)) print(type(RepositoryState)) RepositoryState.uExpired <enum 'RepositoryState'> <class 'enum.EnumType'>
  2. iqrf

    Using Delphi enum in Python

    Thank you, I got to that too var a := VarPythonCreate(pColor).value the second way var valueObj := PyObject_GetAttrString(pColor, 'value'); if Assigned(valueObj) then begin a := PyLong_AsLong(valueObj); Py_XDECREF(valueObj); end else PyErr_Print();
  3. iqrf

    Using Delphi enum in Python

    Hi, how to use PyArg_ParseTupleAndKeywords to get the value of a function parameter that is of type Python enum. E.g class color (enum): RED = 5 GREEN = 8 BLUE = 9 TestFunction (Color.RED) var pColor: PPyObject; if (PyArg_ParseTupleAndKeywords(args, kwargs, '|O', @keyPointerArray[0], @pColor) <> 0) then begin PyEnum_Check(pColor) returns False why? How to get value 5 from pColor? I tried this too var a := VarPythonCreate(pColor); VarIsEnum(a) also returns False in 'a' is the string 'color.RED' Thank you for your help.
  4. iqrf

    Using Delphi enum in Python

    OK 😞 So I define an enum in python and use it in delphi, which works. Now I understand why it is like this: procedure TButtonsRegistration.DefineVars(APyDelphiWrapper: TPyDelphiWrapper); begin inherited; APyDelphiWrapper.DefineVar('bkCustom', bkCustom); APyDelphiWrapper.DefineVar('bkOK', bkOK); APyDelphiWrapper.DefineVar('bkCancel', bkCancel); APyDelphiWrapper.DefineVar('bkHelp', bkHelp); APyDelphiWrapper.DefineVar('bkYes', bkYes); APyDelphiWrapper.DefineVar('bkNo', bkNo); APyDelphiWrapper.DefineVar('bkClose', bkClose); APyDelphiWrapper.DefineVar('bkAbort', bkAbort); APyDelphiWrapper.DefineVar('bkRetry', bkRetry); APyDelphiWrapper.DefineVar('bkIgnore', bkIgnore); APyDelphiWrapper.DefineVar('bkAll', bkAll); end; Thanks for your time.
  5. iqrf

    Using Delphi enum in Python

    Sure this is ok. I would like in Python a = TColor.RED print(type(a)) ### <enum 'TColor'> where TColor defined in Delphi
  6. iqrf

    Using Delphi enum in Python

    I don't want to define an enum in both Delphi and Python. I just want to use an enum defined in Delphi in Python. WrapDelphi I use both FPythonWrapper.DefineVar() and FPythonWrapper.Wrap(TDelphi, soOwned) and FPythonWrapper.RegisterDelphiWrapper(TPyClassWrapper<...>).Initialize But I have no idea how to use the same functionality for an enumeration type.
  7. iqrf

    Using Delphi enum in Python

    Thanks a lot. And how do I get the enumerated type TColor into Python?
  8. iqrf

    Using Delphi enum in Python

    I don't understand how I can write in Python a = TColor.RED without exporting to Python? var colorEnum := MainModule.Color; var Red := colorEnum.RED; result := Red; E2010 Incompatible types: 'PPyObject' and 'Variant' But that's the variant type, I need to return a PPyObject. Thanks
  9. How to export from delphi to python type TColor = (RED = 5, GREEN = 8, BLUE = 9) and in the return value of the delphi function called from Python to return a PPyObject of type TColor. Is it any other way than clumsily like this? FEngine.PyRun_SimpleString('from enum import Enum' + #13 + 'Color = Enum(''Color'', {''RED'':5, ''GREEN'':8, ''BLUE'':9})'); ... FEngine.ExecString(UTF8Encode(FScript), UTF8Encode(FCode.Path)); ... //result my function mainModule, colorEnum, redColor: PPyObject; .... mainModule := PyImport_AddModule('__main__'); colorEnum := PyObject_GetAttrString(mainModule, 'Color'); redColor := PyObject_GetAttrString(colorEnum, 'RED'); result := redColor; ... if mymodule.test_func() == Color.RED: ... Thanks for the ideas.
  10. iqrf

    TPyDelphiWrapper - memory leaks

    Hi, not using exit() is not the solution for me. Users use exit() when debugging a script. If to ProcessSystemExit; i add Py_DecRef(errtraceback); so the memory leak problem will disappear. The destructor TTerminalLogSettings will already be called. I have no idea, but how is that possible. procedure TPythonEngine.CheckError(ACatchStopEx : Boolean = False); procedure ProcessSystemExit; var errtype, errvalue, errtraceback: PPyObject; SErrValue: string; begin PyErr_Fetch(errtype, errvalue, errtraceback); Traceback.Refresh(errtraceback); SErrValue := PyObjectAsString(errvalue); Py_DecRef(errtraceback); // workaround PyErr_Clear; raise EPySystemExit.CreateResFmt(@SPyExcSystemError, [SErrValue]); end;
  11. It is possible to somehow distinguish whether the SetVisible function was called from new_column.visible = True or myPoint.ColumnA['Note1'].Visible = True procedure TColumn.SetVisible(const Value: Boolean); begin FVisible := Value; ... end; Thanks for the advice.
  12. Hi, i have this code TColumn = class(TPersistent) private FHeaderName: String; FVisible: Boolean; FWidth: Integer; FPosition: Integer; procedure SetHeaderName(const Value: String); procedure SetVisible(const Value: Boolean); procedure SetWidth(const Value: Integer); procedure SetPosition(const Value: Integer); public property HeaderName: String read FHeaderName write SetHeaderName; property Visible: Boolean read FVisible write SetVisible; property Width: Integer read FWidth write SetWidth; property Position: Integer read FPosition write SetPosition; end; TColumnWrapper = class(TPyClassWrapper<TColumn>) constructor CreateWith(APythonType: TPythonType; args, kwds: PPyObject); override; end; TTerminalLogSettings = class(TPersistent) private fColumn: TDictionary<String,TColumn>; function GetAutoScroll: Boolean; function GetSeparatorH: Boolean; function GetSeparatorV: Boolean; function GetViewData: Boolean; procedure SetAutoScroll(const Value: Boolean); procedure SetSeparatorH(const Value: Boolean); procedure SetSeparatorV(const Value: Boolean); procedure SetViewData(const Value: Boolean); public constructor Create; destructor Destroy; override; property AutoScroll: Boolean read GetAutoScroll write SetAutoScroll; property SeparatorH: Boolean read GetSeparatorH write SetSeparatorH; property SeparatorV: Boolean read GetSeparatorV write SetSeparatorV; property ViewData: Boolean read GetViewData write SetViewData; property Column: TDictionary<String, TColumn> read fColumn write fColumn; end; ... FPythonModule_TerminalLog := TPythonModule.Create(nil); FPythonModule_TerminalLog.Name := 'FPythonModule_TerminalLog'; FPythonModule_TerminalLog.Engine := FEngine; FPythonModule_TerminalLog.ModuleName := 'terminal_log'; FPythonModule_TerminalLog.OnInitialization := OnInitialization_TerminalLog; FPythonModule_TerminalLog.OnAfterInitialization := OnAfterInitialization_TerminalLog; ... FPythonVersion.AssignTo(FEngine); FEngine.LoadDll; ... terminalLogSettings := TTerminalLogSettings.Create; pTerminalLogSettings := FPythonWrapper.Wrap(terminalLogSettings, soOwned); FPythonModule_TerminalLog.SetVar( 'settings', pTerminalLogSettings); FEngine.Py_DecRef(pTerminalLogSettings); FPythonWrapper.RegisterDelphiWrapper(TColumnWrapper).Initialize; FPythonWrapper.RegisterDelphiWrapper(TPyClassWrapper<TDictionary<string, TColumn>>).Initialize; ... if used in this way in the script, then after the script finishes I correctly call the TTerminalLogSettings destructor and free the memory ... iqrfide.terminal_log.settings.autoScroll = True ... settings_object = iqrfide.terminal_log.settings setattr(settings_object, 'autoScroll', True) ... If the script is interrupted using exit(), the destructor is not called and the memory is not freed. Any explanation? ... iqrfide.terminal_log.settings.autoScroll = True ... settings_object = iqrfide.terminal_log.settings setattr(settings_object, 'autoScroll', True) exit() ... Putting settings_object = None before exit solves the problem.
  13. Is there any way to iterate over TDictionary in Python? for key in spam.myPoint.ColumnA.Keys: #TypeError: 'Object' object is not iterable print(key) for key, value in spam.myPoint.ColumnA.Items: #TypeError: 'IndexedProperty' object is not iterable print(key, value)
  14. Many thanks once again. Question about TPyPoint. From python it is always called CreateWith, you cannot call Create. Why is that? I solved it like this. To write p = spam.Point() , I changed ii: to |ii PyArg_ParseTupleAndKeywords(args, kwds, '|ii:CreatePoint', @KeyPointerArray[0], @fx, @fy)
  15. Of course it works. I don't know how to put elements of type TColumn into a dictionary ColumnA in Python. This doesn't work col = spam.myPoint.Column() col.Visible = True col.Width = 255 spam.myPoint.ColumnA.["Note1"] = col or spam.myPoint.ColumnA.["Note1"] = spam.myPoint.Column(True, 255)
×