eivindbakkestuen 47 Posted September 30 Using the WrapDelphi and associated classes, I have probably missed it, but I couldn't see an equivalent to the CreateComponent() method to create non-TComponent descendant classes, eg TStringList etc which I needed for things in the .PY script below. Is there an existing way of creating such classes on the fly in the .PY script? ... db = CreateComponent("TnxDatabase", None) sl = TStringList (?) db.GetTableList(sl) print(*sl) ... I added the following method and registered it, and now I can do sl = CreateClass("TStringList", None) and it works. If there's no such built in method, feel free to assimilate this method into the WrapDelphi unit. 🙂 function TPyDelphiWrapper.CreateClass(pself, args: PPyObject): PPyObject; // Exposed function at the Module level // CreateClass(ClassName, Owner) var KlassName : PAnsiChar; _obj : PPyObject; Klass : TClass; _comp : TObject; TheClass : TObject; Ownership : TObjectOwnership; begin Result := nil; CheckEngine; with Engine do begin if PyArg_ParseTuple( args, 'sO:CreateDelphiClass', @KlassName, @_obj ) <> 0 then begin try Klass := GetClass(string(KlassName)); except Klass := nil; end; if (Klass = nil) or not Klass.InheritsFrom(TObject) then begin PyErr_SetString(PyExc_TypeError^, PAnsiChar(EncodeString( Format(rs_ErrInvalidArgs, ['CreateClass', rs_InvalidClass])))); Exit; end; TheClass := TClass(Klass).Create; Ownership := soOwned; Result := Self.Wrap(TheClass, Ownership); end else PyErr_SetString(PyExc_TypeError^, PAnsiChar(EncodeString( Format(rs_ErrInvalidArgs, ['CreateClass', ''])))); end; end; Share this post Link to post
pyscripter 689 Posted October 1 (edited) The recommended way to expose classes is to use TPyClassWrapper<T: class>. If for example you have a class TMyClass you want to expose to python, you can use the above from unit wrappers as follows: PyDelphiWrapper1.RegisterDelphiWrapper(TPyClassWrapper<TMyClass>); or at runtime (e.g. inside the FormCreate handler: PyDelphiWrapper1.RegisterDelphiWrapper(TPyClassWrapper<TMyClass>).Initialize; If you want your class to capable of being instantiated from python then do: TMyClassWrapper = class(TPyClassWrapper<TMyClass>) constructor CreateWith(APythonType: TPythonType; args, kwds: PPyObject); overload; override; end; constuctor TMyClassWrapper.CreateWith(APythonType: TPythonType; args, kwds: PPyObject); begin Create(APythonType); DelphiObject := TMyClass.Create; end; and in the FormCreate handler: PyDelphiWrapper1.RegisterDelphiWrapper(TMyClassWrapper).Initialize; In your python script you can then create instances using the pythonic from delphi_module import MyClass obj = MyClass() With TStringList is a bit more complicated since the superclass TStrings has already been exposed. To maintain the TStrings functionality you need to do the following: type TStringListWrapper = class(TPyDelphiStrings) private function GetDelphiObject: TStringList; procedure SetDelphiObject(const Value: TStringList); public constructor CreateWith(APythonType: TPythonType; args, kwds: PPyObject); overload; override; class function DelphiObjectClass : TClass; override; class procedure RegisterMethods( PythonType : TPythonType ); override; class procedure RegisterGetSets( PythonType : TPythonType ); override; // Properties property DelphiObject: TStringList read GetDelphiObject write SetDelphiObject; end; class function TStringListWrapper.DelphiObjectClass: TClass; begin Result := TStringList; end; function TStringListWrapper.GetDelphiObject: TStringList; begin Result := inherited DelphiObject as TStringList; end; class procedure TStringListWrapper.RegisterGetSets(PythonType: TPythonType); begin // Do not call inherited end; class procedure TStringListWrapper.RegisterMethods(PythonType: TPythonType); begin // Do not call inherited end; procedure TStringListWrapper.SetDelphiObject(const Value: TStringList); begin inherited DelphiObject := Value; end; constructor TStringListWrapper.CreateWith(APythonType: TPythonType; args, kwds: PPyObject); begin Create(APythonType); DelphiObject := TStringList.Create; end; and in the FormCreate handler: PyDelphiWrapper1.RegisterDelphiWrapper(TStringListWrapper).Initialize; You can then use it in your python scripts as follows: from delphi_module import StringList sl = StringList() sl.Add("abc") print(sl[0]) Edited October 1 by pyscripter Share this post Link to post