Jump to content

pyscripter

Members
  • Content Count

    778
  • Joined

  • Last visited

  • Days Won

    41

Everything posted by pyscripter

  1. pyscripter

    convert native object instance to wrapped instance

    See TPyDelphiWrapper.Wrap(AObj: TObject; AOwnership: TObjectOwnership): PPyObject; Also you do need need your TPyEventFromScript. This is the old and hard way. You can use instead (e.g. in your FormCreate): PyDelphiWrapper1.RegisterDelphiWrapper(TPyClassWrapper<TEventFromScript>).Initialize; Since you are using interfaces there is also: function TPyDelphiWrapper.WrapInterface(const IValue: TValue): PPyObject;
  2. pyscripter

    New ChatLLM application.

    I have created a new Delphi application called ChatLLM for chatting with Large Language Models (LLMs). Its primary purpose is to act as a coding assistant. Features: Supports both cloud based LLM models (ChatGPT) and local models using Ollama. Supports both the legacy completions and the chat/completions endpoints. The chat is organized around multiple topics. Can save and restore the chat history and settings. Streamlined user interface. Syntax highlighting of code (python and pascal). High-DPI awareness. The application uses standard HTTP client and JSON components from the Delphi RTL and can be easily integrated in other Delphi applications. You do not need an API key to use Ollama models and usage is free. It provides access to a large number of LLM models such as codegemma from Google and codelllama from Meta. The downside is that it may take a long time to get answers, depending on the question, the size of the model and the power of your CPU and GPU. Chat topics The chat is organized around topics. You can create new topics and move back and forth between the topics using the next/previous buttons on the toolbar. When you save the chat all topics are soved and then restored when you next start the application. Questions within a topic are asked in the context of the previous questions and answers of that topic. Screenshots: Settings using gpt-3.5-turbo, which is cheaper and faster than gpt-4: UI: Further prompting: The code is not actually correct (Serialize returns a string) but it is close. If you want to test ChatLLM you can download the executable.
  3. There have been a lot of questions in this forum about running python code in threads using Python4Delphi. I have created a comprehensive guide in this Wiki topic.
  4. pyscripter

    Running python code in Delphi threads

    @maomao2028 Works fine here without memory leaks. See attached project. Note the use of DelayWrites := True in the PythonGUIInputOutput and the calls to TPythonThread.Py_End_Allow_Threads and TPythonThread.Py_Begin_Allow_Threads. Demo01.zip
  5. pyscripter

    Adding docs strings to wrapped functions

    Forgot to say that unfortunately you cannot just set the __doc__ property of Wrapped classes and methods. It has to be done at the time of wrapping. A trivial implementation of IDocServer would be: uses TypInfo; type TMyDocServer = class(TInterfacedObject, IDocServer) private function ReadTypeDocStr(ATypeInfo: PTypeInfo; out ADocStr: string): Boolean; function ReadMemberDocStr(AMember: TRttiMember; out ADocStr: string): Boolean; procedure Initialize; procedure Finalize; function Initialized: Boolean; end;{ TMyDocServer } procedure TMyDocServer.Finalize; begin end; procedure TMyDocServer.Initialize; begin end; function TMyDocServer.Initialized: Boolean; begin Result := True; end; function TMyDocServer.ReadMemberDocStr(AMember: TRttiMember; out ADocStr: string): Boolean; begin Result := False; if AMember.Name = 'getVersion' then begin Result := True; ADocStr := 'getVersion'; end; end; function TMyDocServer.ReadTypeDocStr(ATypeInfo: PTypeInfo; out ADocStr: string): Boolean; begin Result := False; if ATypeInfo = TypeInfo(ThostAPI ) then begin Result := True; ADocStr := 'ThostAPI doc'; end; end; and then PyDocServer := TMyDocServer.Create; DelphiWrapper.RegisterDelphiWrapper(TPyClassWrapper<THostAPI>).Initialize;
  6. pyscripter

    Adding docs strings to wrapped functions

    WrapDelphi defines the following: IDocServer = interface ['{4AF0D319-47E9-4F0A-9C71-97B8CBB559FF}'] function ReadTypeDocStr(ATypeInfo: PTypeInfo; out ADocStr: string): Boolean; function ReadMemberDocStr(AMember: TRttiMember; out ADocStr: string): Boolean; procedure Initialize; procedure Finalize; function Initialized: Boolean; end; var PyDocServer: IDocServer = nil; You need to implement the interface and assign the implemented interface to PyDocServer. PythonDocs.pas provides an implementation based on xml files, which is used by delphivcl and delphifmx. But if, what you are after is to provide docstrings to a few methods, it would be easier to create your own implementation.
  7. System.AnsiStrings.AnsiCompareStr under POSIX converts the ansistrings to UnicodeStrings and then compares. FPC has a function UTF8CompareStr, which sounds promising, but it also converts the ansi strings to UTF-16 and then compares them. Unfortunately it appears that there is no good way to directly compare utf8 strings without converting them. I hope I am wrong.
  8. Unfortunately (see CompareStringA function (winnls.h) - Win32 apps | Microsoft Learn😞 It also appears that System.AnsiStrings.AnsiCompareStr ignores the code page of the ansi strings.
  9. pyscripter

    [help] how to convert delphi TBytes to python Bytes

    Look at PyBytes_AsString, or PyBytes_AsStringAndSize functions. For example if obj is a bytes PPyObject. the following converts it to an AnsiString. AnsiString(PyBytes_AsString(obj)) Also PyObjectAsVariant(obj) converts it to a variant. In the opposite direction to create a bytes object in Delphi use PyBytes_FromStringAndSize
  10. Have you updated to the latest sources?
  11. pyscripter

    C Libraries to Delphi

    This may be worth a look: neslib/Chet: C Header Translator for Delphi (github.com). From @Erik@Grijjy
  12. WrapDelphi was designed to expose Delphi classes, records and interfaces to python. So it did not handle PPyObject parameters or return values. You could handle that by using the low-level approach (adding an Event to TPythonModule). However, I have now added to WrapDelphi support for exposing functions with parameters and/or results of type PPyObject. See WrapDelphiTest.pas in the latest version of the pyscripter/python4delphi: Free components that wrap up Python into Delphi and Lazarus (FPC) (github.com) repo. Example: Exposed Method: function TTestRttiAccess.PlaceInNewList(PyObj: PPyObject): PPyObject; begin with GetPythonEngine do begin Result := PyList_New(1); Py_XIncRef(PyObj); PyList_SetItem(Result, 0, PyObj); end; end; Usage in python from delphi import rtti_var list = rtti_var.PlaceInNewList('abc') The corresponding test in WrapDelphiTest: procedure TTestWrapDelphi.TestPPyObjects; var List: Variant; begin List := rtti_var.PlaceInNewList('abc'); Assert.IsTrue(VarIsPythonList(List)); Assert.AreEqual<string>(List.GetItem(0), 'abc'); end;
  13. Does anybody know whether the workaround mentioned by @Uwe Raabe in Parnassus Bookmarks issue - again. - Delphi IDE and APIs - Delphi-PRAXiS [en] (delphipraxis.net) is still needed in Delphi 12.1?
  14. Under Tools, Options, Language, Delphi, Library, I see a new platform in the drop-down list "Selected platform" called "Windows 64 bits (Modern)". This is in addition to "Windows 64 bits". There was no mention of it in today's seminar. Anyone knows what it is and how to use it?
  15. pyscripter

    Using Delphi enum in Python

    PyEnum_Check and VarIsEnum have to do with enumerators and not the enum.Enum class. There are many ways to get the value. Using VarPyth: var a := VarPythonCreate(pColor); var val := a.value
  16. pyscripter

    mainmodule.<functionname> dynamically?

    Note that if you get the PyObject corresponding to the function by using for instance var PyMainModule: PPyObject; PyFunc: PPyObject; PyMainModule := GetPythonEngine.GetMainModule; PyFunc := GetPythonEngine.PyObject_GetAttrString (PyMainModule, PAnsiChar(AnsiString(method_name))); // When you finish with PyFunc you need to decrease the refcount You can then call the function in a number of different ways including the relatively high level: function EvalFunction(pyfunc:PPyObject; const args: array of const): Variant;
  17. pyscripter

    mainmodule.<functionname> dynamically?

    How about reading the documentation of PyObject_CallMethod or just googling for example usage?
  18. pyscripter

    mainmodule.<functionname> dynamically?

    @Remy Lebeau approach should work. (not tested) Alternatively you can use the more efficient: var PyMainModule: PPyObject; PyMainModule := GetPythonEngine.GetMainModule; GetPythonEngine.PyObject_CallMethod (PyMainModule, PAnsiChar(AnsiString(method_name)), nil);
  19. pyscripter

    Using Delphi enum in Python

    It's not how it works.
  20. pyscripter

    Using Delphi enum in Python

    As mentioned above you just use python strings in place of enumerated values, eg. exported delphi method using WrapDelphi procedure Test(Color: TColor) in python Test('RED')
  21. pyscripter

    Using Delphi enum in Python

    I have no idea what you are trying to do, but it does not make sense to define the enumeration both in Delphi and in Python. I recommend that you familiarize yourself with: WrapDelphi - high level access to Delphi from python VarPyth - high level access to python from Delphi. The video tutorials offer a good introduction to both. If you use WrapDelphi to export delphi functions to python then you just use python strings in place of enumeration values.
  22. pyscripter

    Using Delphi enum in Python

    result := ExtractPythonObjectFrom(Red);
  23. pyscripter

    Using Delphi enum in Python

    There is no need to export anything. Delphi enum values are converted to python strings and sets to lists of strings. On the opposite direction you can access python enum values from Delphi in the same way you access other objects. The easiest way is to use VarPyth. var colorEnum := MainModule.Color var Red := colorEnum.RED
  24. pyscripter

    Versioning in my program

    @Lainkes Under Project, Options, Version Info, you can choose to include version info with your project. The version info includes the version number but also a number of other strings including Comments. Your application can read those in a number of ways. See for instance How to determine Delphi Application Version - Stack Overflow, The most comprehensive way I found is using the Jcl library's unit JclFileInfo. This unit includes a class TJclFileVersionInfo which provides easy access to all information stored in version info. Here is for example a function that retrieves the version number using jcl: function ApplicationVersion : string; var ExeFile : string; begin ExeFile := Application.ExeName; if VersionResourceAvailable(ExeFile) then begin with TJclFileVersionInfo.Create(ExeFile) do begin Result := BinFileVersion; Free; end; end else Result := '1.0.0'; end; Note that this approach is Windows only. For Andoid apps you can access the version info differently (e,g,How can I get at the file version info of a file when running Delphi on Android? - Stack Overflow)
  25. pyscripter

    How I can clear engine after exec script ?

    You need to decrease the refcount of these pyobjects after using them.
×