quarta-feira, 23 de março de 2022

          Delphi4Python GUI libraries

How does Python load Delphi’s VCL and FMX?


Lucas M. Belo
Priyatham K.

Overview


Embarcadero recently presented the DelphiVCL for Python and DelphiFMX for Python libraries to develop graphical interfaces in Python. These libraries are extension modules for Python developed using Embarcadero Delphi. 


Python's C API is used to create extension modules. Loading Python’s C API is a critical factor when using extension modules. This paper covers some specific configuration issues used to gain access to the correct Python interpreter. 


The new Python interpreter loading standard implemented by the Python4Delphi library simplifies this process, making it more compatible and reliable. 


Introduction


The Delphi4Python GUI libraries are available for Python as extension modules. Therefore, following the specifications for using Python's C API to create an extension module is necessary. These specifications are established by the Index of Python Enhancement Proposals – PEP, specifically PEP 7 – Style Guide for C Code. Once defined, they ideally never change. 


For Python to load an extension module, it is necessary to provide an access interface for the interpreter. This interface follows a pattern determined by PEP, a function with its name defined by PyInit_[ModuleName]. The result is a Python structure of type PyObject. Thus, for instance, the DelphiVCL and DelphiFMX modules, respectively, will have the following interfaces:

  1. PyInit_DelphiVCL

  2. PyInit_DelphiFMX

Having this in mind, we understand that an extension module in Python must provide an accessor function, which will return a Python module of type PyObject. This raises the questions:

  • What is the PyObject type? 

  • And what does all this have to do with loading extension modules in Python? 

To explain this, we will need to understand a little more about Python's C API.


Python C API

Python's C API exposes access to the Python interpreter, which allows other programming languages to consume the interpreter. The reasons for using the Python C API are fundamentally divided into two options:

  • Using Python as a component in an application: Sometimes applications written in other programming languages need access to libraries written in Python. This option allows them to “embed” the Python interpreter, gaining access to execute specific routines from Python libraries and scripts.

  • Extension modules: These extend Python's functionality through other programming languages. Improving certain routines' performance or gaining access to C library routines and system calls. This is the process that brings the Delphi VCL and FMX libraries to Python!


Extension Modules


Through the extension modules, we can create an access interface for Python to communicate with our custom modules. 


Detailing this process a little better, we create a Python module through the C API, using the PyObject type. This type is a pointer to an "opaque" data type representing an arbitrary Python object. Then, Python can load and import the created Python module using the access interface we created.


It's quite easy to create extension modules when using Delphi through the Python4Delphi library!


The Python4Delphi library allows developers to create wrappers for the numerous types provided by Delphi's run-time library (RTL), as well as the Visual Component Library (VCL) and Firemonkey (FMX) GUI libraries. 


Then, we can create Python modules, assign wrappers, and provide module access to Python. That's basically it! 


We use the Python4Delphi library, which consumes the Python's C API, to create wrappers for Delphi types. Then we provide access to those wrappers to Python through a module represented by the PyObject type offered by the C API.


Finally, back to the main topic: how do DelphiVCL and DelphiFMX libraries load the Python interpreter?


Loading the Python interpreter


In order for the Python4Delphi library to provide us with access to the routines and structures, which we will call symbols, from the C API, we first need to load the Python interpreter in the host process. Something already came to mind, right? Well, we should add a few notes… Where is Python’s C API located? Which version of the interpreter should we load? And these are some of the problems that the new Python interpreter load standard, implemented in Python4Delphi, has already solved.

Basically, when importing an extension library, we can assume that the Python interpreter is already loaded in the host process, since to import a Python module, it is necessary that the Python interpreter is already running, right?

- Right!

It looks like things got a little simpler, as we won’t have to deal with those issues of interpreter version, C API installation location, etc. So, in summary, there are basically two ways to provide access to the symbols exported by the C API (remembering that the interpreter is already loaded in the host process):

  1. Shared library – in this way, the Python interpreter is loaded at run-time by the Python executable. The interpreter will be loaded by the calling of the “LoadLibrary'' routine. Then the library will be added to the loaded library map and all symbols exposed by the library will be available for usage.

  2. Host symbols – the difference in this method is the fact that all the exported symbols are directly provided by the Python executable. 


Taking advantage of this, Python4Delphi’s only mission is to locate the C API symbols in the host process (the Python executable) or to loop through all shared libraries searching for the Python interpreter. Curious? Take a look at the code implementation in TryLoadFromHostSymbols and TryLoadFromCurrentProcess located in the TDynamicDll class of the Python4Delphi library.


Exception


Some Python distributions do not provide access to C API symbols, which prevents us from using extension modules. So, before using the Delphi4Python GUI libraries, make sure your Python compilation provides the C API symbols in one of the ways mentioned here.

sexta-feira, 25 de setembro de 2020

Reconhecimento de formulários utilizando visão computacional - Python

 Pessoal,

estou elaborando um algoritmo para reconhecer campos de formulários digitalizados utilizando visão computacional. Estou trabalhando principalmente com openCV e mahotas, ambas bibliotecas para visão computacional, além do ambiente de desenvolvimento do Google Colab.

O algoritmo consiste em localizar e extrair formas geométricas retangulares, categorizando-as como campos de escrita.

Este algoritmo cumpre o objetivo didático, logo que na prática existem outras características relevantes ao extrair campos de formulários padronizados que devem ser consideradas, uma vez que , a estrutura do formulário pode variar, a escrita pode extrapolar o retângulo, entre outros...

O experimento foi realizado em uma guia do tipo SP/SADT no padrão TISS. As imagens a seguir mostram os resultados na seguinte sequência: 1) guia original; 2) após aplicação de filtros; 3) após identificação das formas; por fim, extração dos campos.


1)


2)


3)

4)




O arquivo .ipynb está disponível aqui.



sexta-feira, 12 de junho de 2020

UnitFinder - Extensão da IDE do Delphi para localizar units de implementação de aplicativos em depuração

Encontre e abra diretamente na IDE do Delphi as units com a implementação dos formulários do aplicativo em depuração.

A heurística de pesquisa utiliza o nome da classe do formulário selecionado para pesquisar as possíveis units de implementação que estão vinculadas ao projeto aberto na IDE, além de outros diretórios que podem ser previamente configurados. A pesquisa é feita de forma assíncrona, e os resultados são adicionados à interface do localizador no momento em que são localizados.

Utilize o menu de extensão para habilitar a pesquisa. Para executar a pesquisa use as teclas "Ctrl + F1", em seguida será exibido o menu de contexto. As possibilidades serão listadas na interface. Utilize a opção "Abrir no Delphi" para abir a unit de implementação diretamente na IDE .




* Fontes disponíveis aqui.

Até mais!