delphi (XE8 x64, 10, 7)

Описание: Разработка и отладка приложений. Упор на 3D-графику.

dyvniy M
Автор темы, Администратор
Администратор
Аватара
dyvniy M
Автор темы, Администратор
Администратор
Возраст: 41
Репутация: 1
Лояльность: 1
Сообщения: 3579
Зарегистрирован: Ср, 10 октября 2012
С нами: 11 лет 6 месяцев
Профессия: Программист
Откуда: Россия, Москва
ICQ Сайт Skype ВКонтакте

#7 dyvniy » Вт, 16 февраля 2016, 00:28:03

lib ssl
http://indy.fulgan.com/SSL/
Скачать и обновить в системных папках винды при ошибке:
Точка входа в процедуру SSL_COMP_free_compression_methods не
найдена в библиотеке DLL SSLEAY32.dll.
Изображение

dyvniy M
Автор темы, Администратор
Администратор
Аватара
dyvniy M
Автор темы, Администратор
Администратор
Возраст: 41
Репутация: 1
Лояльность: 1
Сообщения: 3579
Зарегистрирован: Ср, 10 октября 2012
С нами: 11 лет 6 месяцев
Профессия: Программист
Откуда: Россия, Москва
ICQ Сайт Skype ВКонтакте

#8 dyvniy » Вт, 22 марта 2016, 19:50:49

Про IdIMAP
http://www.delphifaq.ru/indy-protocols-source-part3/idimap4.html

Его прокси
https://forum.antichat.ru/threads/385642/
Спойлер
1) Добавь на форму IdSSLIOHandlerSocketOpenSSL и IdSocksInfo.
2) В imap ищи IOhandler, и подключи туда IdSSLIOHandlerSocketOpenSSL.
3) В IdSSLIOHandlerSocketOpenSSL ищи TransparentProxy и подключи туда IdSocksInfo.
Затем в компоненте IdSocksInfo есть все что нужно (версия соксов, хост, порт, юзер, пароль).

Код: Выделить всё

imap1.IOhandler:= IdSSLIOHandlerSocketOpenSSL1
IdSSLIOHandlerSocketOpenSSL1.TransparentProxy:=IdSocksInfo1
IdSocksInfo1.host:= 
IdSocksInfo1.port:= 
Изображение

dyvniy M
Автор темы, Администратор
Администратор
Аватара
dyvniy M
Автор темы, Администратор
Администратор
Возраст: 41
Репутация: 1
Лояльность: 1
Сообщения: 3579
Зарегистрирован: Ср, 10 октября 2012
С нами: 11 лет 6 месяцев
Профессия: Программист
Откуда: Россия, Москва
ICQ Сайт Skype ВКонтакте

#9 dyvniy » Ср, 13 апреля 2016, 18:58:55

To python!
http://www.atug.com/andypatterns/pythonDelphiTalk.htm
Спойлер
Using Delphi and Python together

Talk for the Australian Delphi User Group (ADUG), July and August 2001
-Andy Bulka
abulka@netspace.net.au

Delphi = a great object oriented language, and a fantastic RAD environment and framework. You can build excellent GUI's in Delphi that run very fast and have a small .EXE footprint. Runs on linux too. There is a free version of Delphi, too.

Python = is rapidly rising in popularity due to its pseudo-code-like, syntactically minimalist but straightforward syntax. Like the Delphi community, the Python community of programmers has a nice feel about it, and it is committed to developing rich, high quality, open-source class libraries for Python - without the hype of Java.

This paper will demonstrate how to incorporate Python in any of your Delphi apps! Or conversely, how to use Delphi as a GUI for your python apps.

Here is an example of a finished app.



Related 'Python for Delphi' Links on this site:

bullet tutorial - Andy's Python Delphi Tutorial - Getting started with the basics. Also use these techniques if you are using Delphi 5 or below, and Python 2.0 or below. Includes info on getting these free components.
bullet code - Here are Andy's Extensions - a delphi unit that adds a few utility functions to Python for Delphi.
bullet tutorial - Here is a later tutorial using the Latest Techniques in Python for Delphi - use these if you have Delphi 6 and Python 2.1 or higher.
bullet discussion & tips - Here is a discussion and tips on python for delphi deployment issues.
bullet animated slideshow tutorial - Here is an animated visual viewlet demo of using the Python for Delphi components to build a Delphi app that talks to python.
bullet example and screenshot of a Delphi GUI application which uses python code for all its business logic.
return to main Andy Patterns home page



Introduction and Tutorial

Introduction

Create classes in python and have Delphi use these classes as if they were native Delphi classes! Benefit: python can do all the business logic and hard work, whilst Delphi can be used for the GUI and application framework etc.

The interactive shell and fast development time in python makes building business logic here. Define your domain classes and build all the units that do work. Only use Delphi for GUI.

On the other hand, if you want python to talk to and control delphi, then use COM.

Installation

Install Python for win32 Official distribution installer PythonPoweredSmall.gif (361 bytes)

Then install the Python for Delphi components from
http://www.multimania.com/marat/delphi/python.htm

Python for Delphi is a set of components that wrap up the Python 1.5 Dll into Delphi. They let you easily execute Python scripts, create new Python modules and new Python types. You can create Python extensions as Dlls and much more, including being able to create classes in python and have Delphi use these classes as if they were native Delphi classes!

installAutoCompile.gif (8516 bytes)

so you finish up with the following palette:

postInstallPalette1.gif (8131 bytes)which are the engine, the atomEngine, pythonDelphiVar, etc. Note: You only need to use about three of these components to do most of your python-delphi work, the rest are mostly historical or very advanced.

Basic Use - A simple test

A simple Python evaluator:

Create a new Form
Drop a TMemo (or a TRichEdit)
Drop a TPythonGUIInputOutput
for displaying Python's messages
Drop a TMemo for the source code
Drop a TPythonEngine
Connect the attribute IO of the
TPythonEngine to the
TPythonGUIInputOutput.
Connect the attribute Output of
TPythonGUIInputOutput to
the TRichEdit.
Drop a TButton and
call it "Execute script"
Double-click on the button and add:
PythonEngine1.ExecStrings( Memo1.Lines );
Write in the Memo1: some python code e.g. print 2+2 or
that pictured below
Click on the Execute button

simple1.gif (8459 bytes)

click the button and

simple2result.gif (14533 bytes)

python is working with Delphi at a rudimentary level.



The above demonstration is an example of sending strings of code to the python interpreter and receiving Python standard output. You can drive python in this way as much as you like, by pumping text commands to it

PythonEngine.ExecStrings( commandLines )
The above Delphi component wrapper method is not always convenient, since ExecStrings expects commandLines to be a TStrings type, whereas sometimes you want to send a single string to the python interpreter / engine (and not have to create a stringlist) So I wrote a wrapper procedure PyExe (see AndysPythonDelphi extensions) which just takes a string. You can also send multiple lines to PyExe by separating lines with #13 (carriage return) or linefeed.

procedure PyExe(cmds: string;
engine: TAtomPythonEngine);
So that you can do things like:

PyExe('print 5');
PyExe('print 5+23'+#13+'print "welcome"');
// note two commands here
Controlling where Python standard output goes

Every Delphi form must have a PythonEngine component and a PythonInputOutput component.

There are two types of 'PythonIO' components - one that directs all output to a memo or richEdit, or you can use an IO component which lets you define a custom event handler to handle the python output. You can redirect output to raize codesite or even to the standard Delphi Debug Event Log Window: e.g.

Create a new form, add a PythonEngine component and a PythonInputOutput component.
Wire them together (Python engine's IO property to point to the PythonInputOutput component)
Redirect all python standard output to the standard Delphi debug console, by double clicking on the PythonInputOutput component's OnSendData event and putting in the code OutputDebugString( PChar(Data));
PythonDelphiVars

To communicate between Delphi and Python at a deeper level we use the Delphi PythonDelphiVar component. It is a piece of Delphi that the python interpreter / engine can actually see! It looks like this:

pyVar1.gif (5374 bytes)

The most important PythonDelphiVar component property is VarName property which is the name by which python 'sees' this component.

bullet
The Name property of the PythonDelphiVar component is, of course, how Delphi refers to the PythonDelphiVar component.
bullet
The VarName property of the PythonDelphiVar component is how the Python side refers to the PythonDelphiVar component.
In the picture above, from Python's point of view, I have called the PythonDelphiVar component VAR1 which means we can write Python code like:

PyExe('VAR1.Value = 101');
or in a python script, just simply

VAR1.Value = 101
which results in the PythonDelphiVar component having a value of 101. Delphi can access this component's value with

PythonDelphiVar1.ValueAsString
TIP: In practice, I use the convention of making the name of each PythonDelphiVar component and its VarName property the same.

Example #1 - Running an entire python program and storing the results in a set of PythonDelphiVar components.

All Delphi does is trigger off the script (say when a button get hit) and then retieves the results from the PythonDelphiVar components.

The Delphi side:

Create a new form, add a PythonEngine component (name it PE) and a PythonInputOutput component. Wire them together as previously discussed in controlling where the Python output goes to, above.
Drag down two PythonDelphiVar components and name them HEADERVAR and RESULTVAR. Set the VarName properties to the same as their names.
Create a button with the code:
procedure TForm2.Button2Click(Sender: TObject);
begin
PyExeFile('unit2.py', PE);
end;
The Python side

Create a python unit called unit2.py and put it in the same folder as your delphi units. Add the following code to the python unit:
print "Welcome to Python unit2"
HEADERVAR.Value = '----- Welcome -------'
RESULTVAR.Value = 200 * 3
Now run the delphi form and press the button. Our PythonDelphiVar components should be populated. How do we know?

Just add another button with the code:
procedure TForm2.Button3Click(Sender: TObject);
begin
showmessage( HEADERVAR.ValueAsString
+#13+ RESULTVAR.ValueAsString );
end;
Example #2 - Loading an external python program and calling a function in it, storing the result in a PythonDelphiVar component.

The Python side

Modify the unit2.py python script as follows, to include a function which takes a comma separated list of numbers and returns the sum of those numbers. The result is stored in a PythonDelphiVar component named RESULTVAR.

import string

def calcAvg(str):
total = 0
vallist = map(lambda n: int(n), string.split(str,','))
for val in vallist:
total += val
RESULTVAR.Value = total / len(vallist)

The Delphi side:

procedure TForm2.FormCreate(Sender: TObject);
begin
PyExeFile('unit2.py', PE);
// this loads in the python class
end;
procedure TForm2.Button4Click(Sender: TObject);
begin
PyExe('calcAvg("1,5,10")', PE);
showmessage( RESULTVAR.ValueAsString );
end;
Now add an enhancement where, on the Delphi side, you allow the user to type in the list he or she wants to calculate the average on. Add an edit component and a button with the following code.

procedure TForm2.Button5Click(Sender: TObject);
begin
PyExe('calcAvg("' + edit1.text + '")', PE);
showmessage( RESULTVAR.ValueAsString );
end;

pyVar2.gif (1658 bytes) yields 13. Success!



Direct access to Python Classes

First we used stdout to communicate between Delphi and Python.

Then we used special pigeon holes ( PythonDelphiVar components ) to communicate between Delphi and Python.

Now we are going to learn how to gain access to actual Python classes and instances, and call the methods of those instances using normal Delphi dot notation. And of course being able to set and get properties of those instances would be cool too, wouldn't it?

Using TPythonAtom

Basically the technique is to define, in Delphi, some OleVariant variables which hold references to Python objects. We can then access methods and properties on these python objects using the familiar dot syntax that we use in Delphi (and most other languages) e.g.

pythonicCustomer.Address := '23 Smith st.' ;
pythonicCustomer.RunReport() ;
Official documentation on this technique is found in Demo12 of the examples that come with the Python for Delphi components. "Simply add the PythonAtom in the uses clause, declare a new var of type OleVariant and call the function getAtom( any Python object ). It will return a new OleVariant that will let you access properties or methods very simply, as you would do with Word !" See also latest features. Note: if you don't understand the preceding paragraph, that's ok, since you won't have to know about PythonAtom in the next examples, because I have wrapped the difficult stuff up in a simple function or two.

The Delphi side:

Create a new form, and drag down the pythonAtomEngine component and name it PE. Drop a TPythonGUIInputOutput for displaying Python's messages. Connect this to your richtext or memo component. More info on redirecting python IO earlier in this article.
Add AndyDelphiPy, ComCtrls, pythonAtom units to your uses clause, e.g.
implementation

uses AndyDelphiPy, ComCtrls, pythonAtom;

var
aCustomer : OleVariant;
Then in the formshow or formCreate event add the code that loads the main unit of your python code..
procedure TfrmMain.FormShow(Sender: TObject);
begin
PyExeFile('YourPythonApp.py', PE);
At this point the python interpreter has loaded and executed your python classes and any code in the unit you are loading. Now we can create instances of python classes in Delphi and store the references to them in variants.

aCustomer := PyClass('Customer()', pdv, PE);
The above code shows how to instantiate a python class Customer and store that reference in a Delphi variant aCustomer.

The pdv is a necessary intermediate python delphi var used for the instantiation and is not used subsequently. Drag and drop a PythonDelphiVar component and name it "pdv" (the pdv simply stands for python delphi var) and set the Varname property to "pdv" [ ASIDE: ** Matthew Vincent. suggested during the talk that I could perhaps create this pdv component within my PyClass wrapper function, thus eliminating the pdv parameter from the PyClass function. I couldn't get this to work, as the pythonDelphiVar component seems to need to be created at design time - creating it at runtime with the form as the owner worked, but didn't actually satisfy the python engine. Even if this would have worked, we would still have to specify the owning form as a paramter to PyClass, which means we would have gained nothing in terms of the number of parameters we would have had to pass.... ]

Note also that the PyClass delphi function is another one of the AndysPythonDelphi extensions which simplifies the process of instantiating a python class from Delphi. Normally you have to deal with a couple of lines of code and some reference counting, in order to instantiate a python class. By using my wrapper function PyClass the process is reduced to a simple one line call.

When this particular example delphi app runs, after the execution of the FormShow event, the customer instance will have been created and will be ready to be used. Let's add a button so that we can manipulate that instance. Create a button and add the following code:
aCustomer.Surname := 'Bloggs' ;
aCustomer.Address := '23 Smith st.' ;
inc( aCustomer.NumOrders );
showmessage( 'Customer info: ' +
aCustomer.RunReport() );
That's it for the Delphi side of things.

The Python side:

Now let's work on the python side of things, which only involved creating a single python unit named YourPythonApp.py in the same folder as your delphi app.

class Customer:
def __init__(self, surname=''):
self.Surname = surname
self.Address = 'unknown address'
self.NumOrders = 0
def RunReport(self):
return 'Customer ' + self.Surname +
' of ' + self.Address +
' has made ' + `self.NumOrders` +
' orders so far.'
Note that the method __init__ in the above class is the constructor method (like .Create in Delphi).

Running the Delphi app and clicking the button should give you:

finalVariantsuccess.gif (27441 bytes)

Success!

Passing python objects as parameters

Your Delphi code can now interact seamlessly with python objects. One last thing to watch out for is the situation where your delphi code passes a python instance around as a parameter to other python methods, you cannot simply pass the variant reference e.g.

aCustomer.AddOrder(anOrder) # won't work
instead you must pass the pure python reference. So define a python method in each python class called something like 'myself' e.g.

class Order:
...
def myself(self):
return self
then you will be able to successfully:

aCustomer.AddOrder(anOrder.myself) # works
If you are lucky, you may only need to define the 'myself' function just once, perhaps in some Python base class. And of course you can call the function anything you like, just don't call it 'self' since that already reserved by both Delphi and Python.

Deployment

Easy - no registry settings or anything fancy.

As well as your compiled delphi executable, just add the python dll (only about 500 k) in the folder containing your app, plus a Lib folder containing any extra python units you are using. For example random.py and whrandom.py could be placed into the Lib folder if you had used them. The examples used in this article did not use any extra units (the string unit that we used for string.split is a "built in" unit and so does not need to be supplied with your app).

deploy1.gif (2433 bytes)
plus

deploy2.gif (1854 bytes)

Advanced topic: Here is a discussion and tips on python for delphi deployment issues.



Andy's helpful minor extensions to Python-for-Delphi

These are Andy's extra high-level wrapper functions used and described in this article. These functions use and augment the standard Python-for-Delphi components.



More info on python

If you need further informations on Python, visit the official Web site at http://www.python.org/

Andy's Easy Tips on Reading Python Code

Python is a simple, straightforward and elegant language. It uses standard conventions of accessing methods and properties and is fully OO. Types are associated with objects not variables, so you don’t need to declare variables. Functions are called like afunction(param1, param2) and objects are created from classes the same way e.g. o = MyClass(). Python is case sensitive.

There are no begin end reserved words or { } symbols in Python to indicate code blocks – this is done through indentation. The colon in if lzt: simply means ‘then’. The idiom of testing objects (rather than expressions) in an if statement makes sense as python treats empty lists, None and 0 as false.

Python understands named parameters e.g. In a method call, afunction(From=None) means you are passing None (null / nil) as the ‘From’ parameter, whilst in a method definition From=None means that if the caller does not supply this parameter, then it will default to None.

The first argument of all methods defined inside classes must be ‘self’. This argument fills the role of the reserved word this in C++ or Java or self in Delphi. Most languages supply this parameter (a reference to the current instance) implicitly whereas Python makes this concept explicit. At runtime this parameter is supplied by the system, not the caller of the method, thus the def AddOrder(self, order) method in reality takes one parameter when calling it: AddOrder( order ).

The statement pass means do nothing.

You can return multiple items at once e.g. return (2, 50) and also assign multiple items at once e.g. x, y, z = 0 or even expressions like result, status, errmsg = myfunction(1, 90).

Other class files/modules are imported using import somefile. __init__ methods are simply constructors. Finally, a lambda is just a one line function that reads functionname = lambda paramlist : returnedexpression.

Both Python and JPython (Java Python, now called Jython) are open source, free and available from www.python.org

youneedpython2.gif (5396 bytes) :-)

Related 'Python for Delphi' Links on this site:

bullet tutorial - Andy's Python Delphi Tutorial - Getting started with the basics. Also use these techniques if you are using Delphi 5 or below, and Python 2.0 or below. Includes info on getting these free components.
bullet code - Here are Andy's Extensions - a delphi unit that adds a few utility functions to Python for Delphi.
bullet tutorial - Here is a later tutorial using the Latest Techniques in Python for Delphi - use these if you have Delphi 6 and Python 2.1 or higher.
bullet discussion & tips - Here is a discussion and tips on python for delphi deployment issues.
bullet animated slideshow tutorial - Here is an animated visual viewlet demo of using the Python for Delphi components to build a Delphi app that talks to python.
bullet example and screenshot of a Delphi GUI application which uses python code for all its business logic.
return to main Andy Patterns home page



Ideas from you!

Please add your ideas on this article and Python for Delphi here in this public guest book and share your thoughts with other visitors.



Date:
11/16/01
Time:
2:42:47 AM
Remote User:

Comments

This article doesn't cover the most recent enhancements to python for delphi - I've yet to set aside time to investigate and understand them - if someone could write a few paragraphs on how I could enhance what I have already written with the more modern stuff - that would be greatly appreciated.

Though I have set up a 'latest techniques' link on this page and entered in some initial thoughts...

Andy Bulka http://www.atug.com/andypatterns



Date:
11/16/01
Time:
2:43:19 AM
Remote User:

Comments

Is there a role for using Delphi as a GUI to assist in writing python scripts?

Take, for example, the power, flexibility and simplicity of python lists, dictionaries and tuples: a delphi list box or listview could receive input from the Py trainee and insert same into script templates in the appropriate way depending on purpose of list, ensuring correct syntax.

As Py trainees see how Delphi talks to Python, they can be encouraged to work it the other way round and seek out developers who know Delphi for the GUI end of their own scripts or apps.

I am developing a framework for modelling common law worlds, or spheres of activity, as some of our Canadian judges like to call each "area of law". Obviously, a lifetime would be insufficient for me to make a dent in the details of practice procedures (tasks, steps, activities, associated prescribed forms etc) for each sphere. So it would be quite useful for me to have the domaine experts, in their respective areas of practice, have a way to create scripts for embedding in my framework, by country, state/province, area of law, procedure type and procedure ID. Those scripts could be taken back into Delphi for storage in datasets and off we go with a databank of 'how to's, potentially for the entire common law world.

Until I picked up Learning Python a few weeks ago (for a buck in a book bin) there was, to say the least, a huge gap in my business model. Now, I just have to induce a few thousand lawyers, judges, law students and para legals that Python is so intuitive they can be part of what I might call the Great Unified Legal Procedures Model (GULP'M!).

I've been through the 24 demos in Python4Delphi and see tremendous potential, but know I am missing a lot. Your talk to the ADUG helps, especially with respect to the PythonDelphiVar comp. But I can use a lot more.

Thanks for all the work you've done on this, and for passing along the AndyDelphiPy.pas file.

cheers, mate! Alf Rushworth LeXX:Talk Laware (my tryout name this week) Smart.LX@shaw.ca OR alf.rushworth@shaw.ca

А вот про старенький компонент
http://dondublon.livejournal.com/68416.html
Спойлер
Вступление



Delphi - язык, мягко говоря, не мейнстримовый, поэтому всевозможные наработки и API часто обходят его стороной. Python имеет API для C, на основе которого были сделаны добрыми людьми нужные компоненты. Я очень вскользь пробегусь по вещам, которые задокументированы и более подробно коснусь некоторых проблем, с которыми можно столкнуться, но они не описаны. Заранее прошу прощения за то, что мало времеди уделил оформлению очерка.


Итак.


Почему именно Python?



Причина первая, зачем вообще скрипты. Delphi, как я уже сказал, язык не очень популярный и несколько закостеневший, и Python - хороший способ отделить низкоуровневую логику от высокоуровневой. Кроме того, если ваша программа на Delphi большая и сложная, неплохо бы дать юзеру возможность самому программировать некоторые действия над данными.

Почему же именно Python? В процессе поиска скриптовых расширения я пробовал различные варианты, остановлюсь на некоторых.

- Использование ActiveScript control. Встроен в Windows, работает с COM-объектами, значит, вам надо их программировать. Это процесс сам по себе не простой. У меня не получилось заставить этот компонент работать как полагается.

- Fast Script control (http://www.fast-report.com/ru/products/fast-script.html) Позволяет писать скрипты на четырех языках, в том числе Pascal, что дает возможность написанные скрипты потом встраивать в программу в виде компилируемого кода. Из delphi-специфичных компонентов понравился мне больше всего. Платный.

- Язык Lua. (www.lua.org) Довольно простой язык, заточеный специально под скриптование нативного кода. Библиотека интерпретатора под windows весит всего 54 kb. Попробовал под Delphi, работает хорошо, но конкуренции с Python не выдерживает.

- И, наконец, Python. О самом языке писать не буду, вы все сами наверняка знаете. Позводяет делать практически настоящую объектность, кроме того, под него имеется куча наработок.


О компонентах.



Скачиваем тут: http://www.atug.com/andypatterns/pythonDelphiTalk.htm .
Большое предупреждение: работа над компонентами давно прекращена , поэтому установку на новые версии и некоторые плюшечки придется делать самому.

Для Delphi 2007 и ранее ставится без проблем, для 2010 придется сделать небольшие правки в связи с переходом на Unicode. Я их не делал, так что готовый рецепт не предоставлю.

Справка для компонентов небогата, поэтому я и решил написать этот очерк.

Примеры использования находятся в подкаталоге Demos каталога установки, для облегчения себе жизни я написал краткое оглавление примеров:


01-07 - совсем элементарные примеры по подключению и вызовам.
08 - базовая работа с объектом
09 - вызов из dll-ки
10 - работа с БД
11 - сортировка
12 - Atom, работа через ole и позднее связывание
13 - БД
14 - БД
15 - БД
16 - работа со словарем
17 - variant array
18 - c++ builder
19 - c++ builder
20 - c++ builder
21 - объект, с событиями
22 - threading
23 - то же
24 - variants в параметрах, извлечение объектов
25 - тесты
26 - объекты, наследование
27 - тривиальный sequence
28 - итератор
29 - работа с растровой картинкой
30 - позднее связывание
31 - работа с готовыми обертками VCL
32 - видимо, обертка над объектом с помощью RTTI, не работает.


Кратко о Python



Как вы уже наверняка знаете, в Python все является объектом. На практике это значит, что любая переменная Python может поддерживать (а может и не поддерживать) какие-то методы общего предка всех питоновских объектов, поддерживаемые на уровне языка.


Основа связки Delphi-Python



Релизация вышеуказанных методов в ваших дельфийских объектах, наследниках TPyObject, и будет основой для ваших переменных, видимых одновременно из Delphi и Python. Пример элементарного объекта описан в примере 8. Далее я буду исходить из предположения, что вы с ним ознакомились.

Весь API Python'а работает с указателем на PyObject, в Delphi он называется PPyObject.


Вызов delphi-функций.



Python API работает с С-функциями определенного вида, (какого именно - можно посмотреть в примерах) поэтому не забывайте указывать в конце cdecl. На выходе функция должна обязательно возвращать PPyObject, иначе будет Access violation. Если логически функция ничего возвращать не должна, верните TPythonEngine.ReturnNone.


Как получить из PPyObject - TPyObject и наоборот?


Не надо использовать "@" и "^"!

Для первого - использовать функцию PythonToDelphi.

var
myobj: TmyPyObject; // наследние TPyObject;
p: PpyObject;
... begin ...
myobj := TmyPyObject(PythonToDelphi(p));
...

Для второго - использовать метод TPyObject.GetSelf.

О python-овских ссылках на объекты.



Если вы просто возвращаете в python объект в виде указателя, то вполне возможна ситуация, когда этот объект изчезнет, а вместо него потом автоматически будет создан новый, но уже с другими данными. Например, для такого вызова (python):


myobj = mymodule.GetMainStorage().GetObject

после этого вызова то, что было возвращено GetMainStorage() - изчезнет, а вместо myobj будет создан новый объект. Чтобы не было такой путаницы, используйте повышение счетчика питоновских ссылок:
function GetMainStorage( self, args : PPyObject ) : PPyObject; cdecl;
var
p: PPyObject;
begin
with GetPythonEngine do
begin
p := FFrame.pytDocument.CreateInstance; // FFrame.pytDocument = TpythonType
FMainStorage := TPyDoc(PythonToDelphi(p));
if Assigned(FdelphiMainStorage) then
FMainStorage.FObject := FdelphiMainStorage;
Result := p;
Py_INCREF(p);
end;
end;

Здесь не так существенно что, что ссылка на объект FMainStorage живет в Delphi долго, а то, что на него делается ссылка в python, вызовом Py_INCREF(p).

function TMainStorage.GetAttr(key: PChar): PPyObject;
var
p: PPyObject;
pyobj: TPySomeObject;
pycube: TPyCube;
// pyhist: TPyHistoryStorage;
ck: Integer;
begin
with GetPythonEngine do
begin
if UpperCase(key) = 'GETOBJECT' then
begin
p := FFrame.pytSomeObject.CreateInstance; // FFrame.pytSomeObject = TpythonType
pyobj := TPySomeObject( PythonToDelphi(p) );
// какие-то другие присвоения
Result := p;
Py_INCREF(p);
end;
...


Утечки памяти



После работы скрипта все объекты типа TPyObject уничтожаюся сами. Если объект представлял собой обертку для вашего рабочего объекта и держал на него ссылку, уничтожение ссылки коректно не делается и вы получите утечки памяти. Я достаточно долго ломал голову, как разрулить этот вопрос, в итоге получил рецепт: сделать у каждого такого TPyObject метод очистки ссылок, вызвать его вручную после работы скрипта, причем - это важно - этот метод должен быть не в деструкторе! Может, есть способ элегантнее, но я его не знаю.


Могу ли я использовать библиотеку NumPy?



Да, можете. Numpy - питоновская библиотека для быстрой работы с числовыми массивами. Эти массивы находятся в памяти подряд, как обычные массивы нативного кода. Python API предоставляет функции для работы с такими участками памяти, но в наших компонентах их выховы отсутствуют, поэтому придется добавить это самостоятельно.


Идем в юнит PythonEngine, в класс TPythonInterface добавляем методы:

PyBuffer_FromMemory: function ( prt: Pointer; Size: Py_ssize_t): PPyObject; cdecl;
PyBuffer_FromReadWriteMemory: function ( prt: Pointer; Size: Py_ssize_t): PPyObject; cdecl;
PyBuffer_New: function ( Size: Py_ssize_t): PPyObject; cdecl;


(PyBuffer_FromMemory выдает участок памяти только для чтения, для возможности записи используйте PyBuffer_FromReadWriteMemory.)


Далее, идем в процедуру TPythonInterface.MapDll и в конец добавляем:

@PyBuffer_FromMemory := Import('PyBuffer_FromMemory');
@PyBuffer_FromReadWriteMemory := Import('PyBuffer_FromReadWriteMemory');
@PyBuffer_New := Import('PyBuffer_New');


Готово, теперь можно пользоваться.

Передаем массив из Delphi так:

function GetFloatArray( self, args : PPyObject ) : PPyObject; cdecl;
begin
result := GetPythonEngine.PyBuffer_FromMemory(@(MyTestArray[0]), 100 * SizeOf(single));
end;

где 100 - это размер вашего массива, single - его тип.

На стороне Python с использованием NumPy принимаем так:

import numpy
v1 = mymodule.GetFloatArray()
#print v1
dt = numpy.dtype(numpy.float32)
na = numpy.frombuffer(v1, dt, 100)
print na

nympy.float64 используется для double, float32 для single, int32 для integer.


Как работать с датой и временем



Я опишу работу со стандартным типом datetime из библиотеки datetime.

Из Python в Delphi:

При распарсивании пришедшего datetime с помощью функции PyArg_ParseTuple в строке Format используйте буковку O, заглавную:

function TPyMyObject.GetSomeData(args: PPyObject): PPyObject;
var
ck: Integer;
source: PChar;
pdt: PPyObject;
...
begin
...
tmp := PyArg_ParseTuple( args, 'isO:MyObject.GetSomeData', [@ck, @source, @pdt] );
...

Затем преобразуйте pdt в дельфийский TdateTime примерно так:

...
var
pdt: PPyDateTime_DateTime;
pd: PPyDateTime_Date;
...

with GetPythonEngine do
begin
if PyDateTime_Check(p) then
begin
pdt := PPyDateTime_DateTime(p);
result := EncodeDate(pdt^.data[0]*256+ pdt^.data[1], pdt^.data[2], pdt^.data[3]);
end
else if PyDate_Check(p) then
begin
// здесь - писать преобразование, если нужна только дата без времени
end
end;

Данный код помещает в DateTime только время без даты, потому что это черновик. В общем, возможны вариации на ваше усмотрение.
Распределение байт в структуре можно посмотреть в юните PythonEngine, в комментарии, начинающимся словами "Fields are packed into successive bytes".
Из Delphi в Python

... это делается значительно проще. Прежде всего, в вашем компоненте TpythonEngine переключите свойство DatetimeConversionMode на dcmToDatetime.
Затем используйте функцию TpythonEngine.VariantToPyObject, с параметром TDateTime, она сама разберется.

Элементарный итератор



Цикл for в Python в общем случае работает так: сначала получаем у объекта итератор, а уж он работает на итерации. Пример итератора есть в демках, в примере 28, но в общем случае усложнять программу дополнительным объектом не стоит и можно совместить, примерно так:
TPyList = class(TPyObject)
private
FCursor: Integer;
FDelphiList: TObjectList;
...

function TPyList.Iter: PPyObject;
begin
FCursor := 0;
result := Self.GetSelf;
GetPythonEngine.Py_INCREF(Result);
end;

function TPyList.IterNext: PPyObject;
var
s: string;
begin
with GetPythonEngine do
begin
if FCursor < FDelphiList.Count then
result := PyList_GetItem(FPyList, FCursor);
else
result := nil; // не ReturnNone!
end;
inc(FCursor);
end;

Когда кончается итерация - это, наверно, единственный случай, когда в функции не надо возвразать PPyObject. Обращаю ваше внимание: для окончания итерации надо просто вернуть nil, создавать python exception StopIteration вам не нужно.

Вызов по индексу


Для вызова из объекта какого-то значения по произвольному индексу используйте функцию (переопределение, разумеется)
function MpSubscript( obj : PPyObject) : PPyObject;

Для присваивания по индексу -
function MpAssSubscript( obj1, obj2 : PPyObject) : Integer;

Вернуть надо 0 в случае успеха, иное число в случае неудачи. В случае неудачи надо также сделать питоновский exception, но я до этого вопроса еще не дошел.

***


На этом все, спасибо за внимание.
Если этот текст оказался вам интересен, прошу не полениться и написать коммент. Так я буду знать, что, в случае, если найдутся еще какие-то достойные внимания приемы, то их неплохо бы выложить публично.
Tags:delphi, python, программирование
Изображение

dyvniy M
Автор темы, Администратор
Администратор
Аватара
dyvniy M
Автор темы, Администратор
Администратор
Возраст: 41
Репутация: 1
Лояльность: 1
Сообщения: 3579
Зарегистрирован: Ср, 10 октября 2012
С нами: 11 лет 6 месяцев
Профессия: Программист
Откуда: Россия, Москва
ICQ Сайт Skype ВКонтакте

#10 dyvniy » Чт, 14 апреля 2016, 10:33:30

Ключ в реестр, чтоб 32 битное приложение поддерживало более 2х гигов памяти.

Код: Выделить всё

{$SetPEFlags IMAGE_FILE_LARGE_ADDRESS_AWARE}
Изображение

dyvniy M
Автор темы, Администратор
Администратор
Аватара
dyvniy M
Автор темы, Администратор
Администратор
Возраст: 41
Репутация: 1
Лояльность: 1
Сообщения: 3579
Зарегистрирован: Ср, 10 октября 2012
С нами: 11 лет 6 месяцев
Профессия: Программист
Откуда: Россия, Москва
ICQ Сайт Skype ВКонтакте

#11 dyvniy » Ср, 20 апреля 2016, 17:21:35

Утечки памяти
http://mirsovetov.net/show-memory-leek.html
ReportMemoryLeaksOnShutdown := true; // внутри dpr
Спойлер
Delphi отображение утечки памяти

Добавить комментарий
Проблема: Проверить существование в программе утечек памяти (Memory leek).
Решение: Для решения даной задачи можно воспользоваться различными инструментариями/компонентами. Приведу некоторые из них:

EurekaLog
FastMM
AQTime
SafeMM
Конечно можно установить или подключить той или иной компонет к проекту и воспользоваться всеми возможностями, которые поставляются. Но, бываю ситуации когда нужно оперативно определить есть утечка паияти или нет, при этом ничего не настраивая или устанавливая. В таком случае нужно установить глобальную переменную ReportMemoryLeaksOnShutdown := True;. По умолчанию данный параметр выключен. При закрытии приложения, если есть утечки памяти, появится окно с сообщением что «течет», и в каком количестве. (Рис. 1):

Memory Leek
Рис. 1 Утечка памяти

Использование: Я бы рекомендовал установить параметр ReportMemoryLeaksOnShutdown в исходном коде проекта (dpr файле) .
Для этого нужно в «Project Manager’е» кликнуть правой кнопкой мыши на проект и выбрать пункт «View Source«, после чего должен открыться редактор кода примерно следующего вида (см. ниже). В секции begin..end устанавливаем парамет ReportMemoryLeaksOnShutdown := true:

program FreeObject;

uses
...
{$R *.res}
begin
//Для отображения утечек памяти, если они есть
ReportMemoryLeaksOnShutdown := true;

Application.Initialize;
Application.MainFormOnTaskbar := True;
Application.CreateForm(TMainForm, MainForm);
Application.Run;
end.
Если в вашем приложении есть утечки памяти, они отображаться при закрытии программы. Отображаться только в том случае если вы работали с какими то классами, которые не были удалены после использования.

Диагностику утечек памяти я применил при написании статьи: TStrings и освобождение объектов, исходники проекта лежат тут
Изображение

dyvniy M
Автор темы, Администратор
Администратор
Аватара
dyvniy M
Автор темы, Администратор
Администратор
Возраст: 41
Репутация: 1
Лояльность: 1
Сообщения: 3579
Зарегистрирован: Ср, 10 октября 2012
С нами: 11 лет 6 месяцев
Профессия: Программист
Откуда: Россия, Москва
ICQ Сайт Skype ВКонтакте

#12 dyvniy » Чт, 21 апреля 2016, 10:19:43

Изображение


Название раздела: Программирование (под Desktop и Android)
Описание: Разработка и отладка приложений. Упор на 3D-графику.

Быстрый ответ


Введите код в точности так, как вы его видите. Регистр символов не имеет значения.
Код подтверждения
:) ;) :hihi: :P :hah: :haha: :angel: :( :st: :_( :cool: 8-| :beee: :ham: :rrr: :grr: :* :secret: :stupid: :music: Ещё смайлики…
   

Вернуться в «Программирование (под Desktop и Android)»

Кто сейчас на форуме (по активности за 15 минут)

Сейчас этот раздел просматривают: 105 гостей