iqrf
Members-
Content Count
44 -
Joined
-
Last visited
Everything posted by iqrf
-
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'>
-
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.
-
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();
-
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.
-
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.
-
Sure this is ok. I would like in Python a = TColor.RED print(type(a)) ### <enum 'TColor'> where TColor defined in Delphi
-
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.
-
Thanks a lot. And how do I get the enumerated type TColor into 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
-
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.
-
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;
-
Wrap TDictionary - TypeError: 'Object' object is not subscriptable
iqrf posted a topic in Python4Delphi
HI, I modified the example of Demo 32. Added TColumn and fColumn: TDictionary<String,TColumn>; property ColumnA: TDictionary<String,TColumn> read fColumn write fColumn; {$METHODINFO ON} TColumn = class(TPersistent) private FVisible: Boolean; FWidth: Integer; public property Visible: Boolean read FVisible write FVisible; property Width: Integer read FWidth write FWidth; end; TPoint = class(TPersistent) private fx, fy : Integer; fName : String; fColumn: TDictionary<String,TColumn>; public procedure OffsetBy( dx, dy : integer ); published property x : integer read fx write fx; property y : integer read fy write fy; property Name : string read fName write fName; property ColumnA: TDictionary<String,TColumn> read fColumn write fColumn; end; {$METHODINFO OFF} procedure TForm1.Button1Click(Sender: TObject); var DelphiPoint : TPoint; p : PPyObject; begin // Here's how you can create/read Python vars from Delphi with // Delphi/Python objects. DelphiPoint := TPoint.Create; DelphiPoint.x := 10; DelphiPoint.y := 20; DelphiPoint.ColumnA := TDictionary<String,TColumn>.Create; var value := TColumn.Create; value.Visible := True; value.Width := 455; DelphiPoint.ColumnA.Add('Note', value); // DelphiPoint will be owned and eventually destroyed by Python p := PyDelphiWrapper.Wrap(DelphiPoint, soOwned); PythonModule1.SetVar( 'myPoint', p ); // Note, that you must not free the delphi point yourself. // Instead use the GetPythonEngine.Py_XDECREF(obj) method, // because the object may be used by another Python object. PythonEngine1.Py_DecRef(p); // Excecute the script PythonEngine1.ExecStrings( memo1.Lines ); end; if i coll print(spam.myPoint.ColumnA.Count) print(spam.myPoint.ColumnA.ContainsKey("Note")) OK 1 True print(spam.myPoint.ColumnA["Note"]) #TypeError: 'Object' object is not subscriptable for key in spam.myPoint.ColumnA: #TypeError: 'Object' object is not iterable print(key) How to solve this please. How to make this work a = spam.myPoint.ColumnA.Column() a.Visible = True a.Width = 111 spam.myPoint.ColumnA.Add("Note1", a) Thanks -
Wrap TDictionary - TypeError: 'Object' object is not subscriptable
iqrf replied to iqrf's topic in Python4Delphi
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. -
Wrap TDictionary - TypeError: 'Object' object is not subscriptable
iqrf replied to iqrf's topic in Python4Delphi
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) -
Wrap TDictionary - TypeError: 'Object' object is not subscriptable
iqrf replied to iqrf's topic in Python4Delphi
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) -
Wrap TDictionary - TypeError: 'Object' object is not subscriptable
iqrf replied to iqrf's topic in Python4Delphi
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) -
Wrap TDictionary - TypeError: 'Object' object is not subscriptable
iqrf replied to iqrf's topic in Python4Delphi
Thank you very, very much. I struggled with it for two days. Please, how to make the TColumn class visible so it works col = spam.myPoint.TColumn() col.Visible = True col.Width = 255 spam.myPoint.ColumnA.["Note1"] = col or spam.myPoint.ColumnA.["Note1"] = spam.myPoint.TColumn(True, 255) or do I have to make TPyColumn = class(TPyDelphiPersistent)? Thanks -
Wrap TDictionary - TypeError: 'Object' object is not subscriptable
iqrf replied to iqrf's topic in Python4Delphi
It doesn't work, the class TPyClassWrapper is not defined anywhere -
Hi, I confirm that both CTRL+F and CTRL+C do not work under Delphi Alexandria + Win11 64b. Not working is: HtmlHelp(0, Application.HelpFile, HH_DISPLAY_TOC, 0); HtmlHelp(0, Application.HelpFile, HH_DISPLAY_INDEX, DWORD(PWideChar(''))); HtmlHelp(0, Application.HelpFile, HH_DISPLAY_SEARCH, DWORD(@Query)); Application.HelpContext() Calling HtmlHelpW instead of HtmlHelp works. A broken Application.HelpContext solved them like this: function TFormMain.ApplicationEvents1Help(Command: Word; Data: NativeInt; var CallHelp: Boolean): Boolean; begin HtmlHelpW(0, PWideChar(Application.HelpFile), HH_HELP_CONTEXT, Data); CallHelp := False; end; I used HH_HELP_CONTEXT because even when calling the Application.HelpContext the Command parameter contained 1 instead of 15. Of course, this solution does not work if HelpKeyword is used for components. A universal solution could be made by possibly recoding these constants. const { Commands to pass to WinHelp() } {$EXTERNALSYM HELP_CONTEXT} HELP_CONTEXT = 1; { Display topic in ulTopic } {$EXTERNALSYM HELP_QUIT} HELP_QUIT = 2; { Terminate help } {$EXTERNALSYM HELP_INDEX} HELP_INDEX = 3; { Display index } {$EXTERNALSYM HELP_CONTENTS} HELP_CONTENTS = 3; {$EXTERNALSYM HELP_HELPONHELP} HELP_HELPONHELP = 4; { Display help on using help } {$EXTERNALSYM HELP_SETINDEX} HELP_SETINDEX = 5; { Set current Index for multi index help } {$EXTERNALSYM HELP_SETCONTENTS} HELP_SETCONTENTS = 5; {$EXTERNALSYM HELP_CONTEXTPOPUP} HELP_CONTEXTPOPUP = 8; {$EXTERNALSYM HELP_FORCEFILE} HELP_FORCEFILE = 9; {$EXTERNALSYM HELP_KEY} HELP_KEY = 257; { Display topic for keyword in offabData } {$EXTERNALSYM HELP_COMMAND} HELP_COMMAND = 258; {$EXTERNALSYM HELP_PARTIALKEY} HELP_PARTIALKEY = 261; {$EXTERNALSYM HELP_MULTIKEY} HELP_MULTIKEY = 513; {$EXTERNALSYM HELP_SETWINPOS} HELP_SETWINPOS = 515; {$EXTERNALSYM HELP_CONTEXTMENU} HELP_CONTEXTMENU = 10; {$EXTERNALSYM HELP_FINDER} HELP_FINDER = 11; {$EXTERNALSYM HELP_WM_HELP} HELP_WM_HELP = 12; {$EXTERNALSYM HELP_SETPOPUP_POS} HELP_SETPOPUP_POS = 13; const {$EXTERNALSYM HH_DISPLAY_TOPIC } HH_DISPLAY_TOPIC = 0; {$EXTERNALSYM HH_HELP_FINDER } HH_HELP_FINDER = 0; {$EXTERNALSYM HH_DISPLAY_TOC } HH_DISPLAY_TOC = 1; {$EXTERNALSYM HH_DISPLAY_INDEX } HH_DISPLAY_INDEX = 2; {$EXTERNALSYM HH_DISPLAY_SEARCH } HH_DISPLAY_SEARCH = 3; {$EXTERNALSYM HH_SET_WIN_TYPE } HH_SET_WIN_TYPE = 4; {$EXTERNALSYM HH_GET_WIN_TYPE } HH_GET_WIN_TYPE = 5; {$EXTERNALSYM HH_GET_WIN_HANDLE } HH_GET_WIN_HANDLE = 6; {$EXTERNALSYM HH_ENUM_INFO_TYPE } HH_ENUM_INFO_TYPE = 7; {$EXTERNALSYM HH_SET_INFO_TYPE } HH_SET_INFO_TYPE = 8; {$EXTERNALSYM HH_SYNC } HH_SYNC = 9; {$EXTERNALSYM HH_KEYWORD_LOOKUP } HH_KEYWORD_LOOKUP = $d; {$EXTERNALSYM HH_DISPLAY_TEXT_POPUP } HH_DISPLAY_TEXT_POPUP = $e; {$EXTERNALSYM HH_HELP_CONTEXT } HH_HELP_CONTEXT = $f; {$EXTERNALSYM HH_TP_HELP_CONTEXTMENU } HH_TP_HELP_CONTEXTMENU = $10; {$EXTERNALSYM HH_TP_HELP_WM_HELP } HH_TP_HELP_WM_HELP = $11; {$EXTERNALSYM HH_CLOSE_ALL } HH_CLOSE_ALL = $12; {$EXTERNALSYM HH_ALINK_LOOKUP } HH_ALINK_LOOKUP = $13; {$EXTERNALSYM HH_GET_LAST_ERROR } HH_GET_LAST_ERROR = $14; {$EXTERNALSYM HH_ENUM_CATEGORY } HH_ENUM_CATEGORY = $15; {$EXTERNALSYM HH_ENUM_CATEGORY_IT } HH_ENUM_CATEGORY_IT = $16; {$EXTERNALSYM HH_RESET_IT_FILTER } HH_RESET_IT_FILTER = $17; {$EXTERNALSYM HH_SET_INCLUSIVE_FILTER } HH_SET_INCLUSIVE_FILTER = $18; {$EXTERNALSYM HH_SET_EXCLUSIVE_FILTER } HH_SET_EXCLUSIVE_FILTER = $19; {$EXTERNALSYM HH_INITIALIZE } HH_INITIALIZE = $1c; {$EXTERNALSYM HH_UNINITIALIZE } HH_UNINITIALIZE = $1d; {$EXTERNALSYM HH_SET_QUERYSERVICE } HH_SET_QUERYSERVICE = $1e; {$EXTERNALSYM HH_PRETRANSLATEMESSAGE } HH_PRETRANSLATEMESSAGE = $fd; {$EXTERNALSYM HH_GLOBALPROPERTY } HH_GLOBALPROPERTY = $fc;
-
Hi, I have a TPythonType object TPyDevice = class(TPyObject) and Interface methods in it function DoSendAndReceive(args: PPyObject): PPyObject; cdecl; function TPyDevice.DoSendAndReceive(args: PPyObject): PPyObject; cdecl; var data: TBytes; pyBytes: PPyObject; timeout: Single; logging: Boolean; begin with GetPythonEngine do begin Adjust(@Self); logging := False; if PyArg_ParseTuple( args, 'S|fp:device.send_and_receive', @pyBytes, @timeout, @logging) <> 0 then begin data := PyBytesAsBytes(pyBytes); var response := False; .... .... if response then begin pyBytes := PyBytes_FromStringAndSize(PAnsiChar(data), Length(data)); Result := pyBytes; end else Result := ReturnNone; end else Result := nil; end; end; I use it like this response = device_manager.device.send_and_receive(dat, 0, True) or response = device_manager.device.send_and_receive(dat) I would like to call the function like this device_manager.device.send_and_receive(data=dat, timeout 0, logging=True) or device_manager.device.send_and_receive(data=dat, logging=True) I edited it like this function TPyDevice.DoSendAndReceive(args, kwds: PPyObject): PPyObject; cdecl; var data: TBytes; pyBytes: PPyObject; timeout: Single; logging: Boolean; keyArray: array of AnsiString; keyPointerArray: array of PAnsiChar; begin with GetPythonEngine do begin Adjust(@Self); logging := False; KeyArray := ['data', 'timeout', 'logging']; KeyPointerArray := [PAnsiChar(KeyArray[0]), PAnsiChar(KeyArray[1]), PAnsiChar(KeyArray[2])]; if PyArg_ParseTupleAndKeywords(args, kwds, 'S|fp:device.send_and_receive', @keyPointerArray[0], @pyBytes, @timeout, @logging) <> 0 then begin data := PyBytesAsBytes(pyBytes); var response := False; .... .... if response then begin pyBytes := PyBytes_FromStringAndSize(PAnsiChar(data), Length(data)); Result := pyBytes; end else Result := ReturnNone; end else Result := nil; end; end; TPyDevice = class(TPyObject) ... constructor CreateWith( PythonType : TPythonType; args : PPyObject ); override; // Basic services function Repr : PPyObject; override; function Str : PPyObject; override; function GetAttr(Key: PAnsiChar): PPyObject; override; function SetAttr(Key: PAnsiChar; Value: PPyObject): Integer; override; // Methods of TPyDevice ... // Class methods class procedure RegisterMethods(PythonType: TPythonType); override; class procedure RegisterMembers(PythonType: TPythonType); override; class procedure RegisterGetSets(PythonType: TPythonType); override; // Interface methods function DoSendAndReceive(args, kwds: PPyObject): PPyObject; cdecl; ... end; class procedure TPyDevice.RegisterMethods(PythonType: TPythonType); begin inherited; with PythonType do begin AddMethod('send_and_receive', @TPyDevice.DoSendAndReceive, 'device_manager.device.send_and_recive(data: bytes)'); .... end; end; FPythonType_Device := TPythonType.Create(nil); FPythonType_Device.Name := 'FPythonType_Device'; FPythonType_Device.GenerateCreateFunction := False; FPythonType_Device.Engine := FEngine; FPythonType_Device.OnInitialization := OnInitialization_PythonType_Device; FPythonType_Device.TypeName := 'Device'; FPythonType_Device.Prefix := ''; FPythonType_Device.Services.Basic := [bsGetAttr, bsSetAttr, bsRepr, bsStr]; FPythonType_Device.Module := FPythonModule_DeviceManager; pDevice := FPythonType_Device.CreateInstance; FEngine.CheckError; device := TPyDevice(PythonToDelphi(pDevice)); FPythonModule_DeviceManager.SetVar('device', pDevice); FEngine.Py_DecRef(pDevice); But I get TypeError: send_and_receive() takes no keyword arguments. Execution of the send_and_receive function will not start at all. I looked at the Demo32 example, but there it is used with CreateWith which has parameters args, kwds: PPyObject already PythoEngine.pas Thank you in advance for your help.
-
I will answer myself. To register a method, you need to use AddMethodWithKeywords instead of AddMethod. It was enough to look at WrapDelphi.pas. I think it would be beneficial if Demo32 included an example of such a method. and still to fix KeyPointerArray := [PAnsiChar(KeyArray[0]), PAnsiChar(KeyArray[1]), PAnsiChar(KeyArray[2]), nil];
-
Yes, according to Demo32 I implemented it. But it is an example of use in CreateWidth. I am trying to use it in a method.
-
It's really not easy, so I'll accept the imperfection and try to solve it sometime in the future. Thanks
-
Hi, Let's take Demo08 as an example where a myPoint object is created in Delphi. I need to detect on the Delphi side if the assignment spam.myPoint = None is made in Python. Cyclic polling using PythonModule1.GetVar('myPoint') is inappropriate for me. I would need something like OnChange in TPythonDelphiVar. I've studied PythonEngine.pas and can't think of anything. Thank you for your opinion.
-
Couldn't this be done at the Python level using a decorator above the module? import types class MyModule(types.ModuleType): def __setattr__(self, name, value): print(f"Setting attribute {name} to value {value}") super().__setattr__(name, value) mymodule = MyModule('mymodule') mymodule.my_attribute = 42 print(mymodule.my_attribute)