Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Начинающим";
Текущий архив: 2005.12.11;
Скачать: [xml.tar.bz2];

Вниз

Странные проблемы с классами   Найти похожие ветки 

 
SkyRanger ©   (2005-11-23 03:54) [0]

Всем привет.
Написал я несколько классов, чтобы облегчить себе работу с модулем Python на делфи...

Вот они:

[code]
{********************************************************}
{                                                        }
{                    pyAPI                               }
{       Copyright (c) 2005 Vasily V. Altunin             }
{                                                        }
{  Разработчик   : Алтунин Василий                       }
{                  (skyr@users.sourceforge.net)          }
{  Модифицирован : 23.11.2005                            }
{  Версия        : 0.01                                  }
{  Вы можете изменять и использовать код приведенный     }
{  ниже на свое усмотрение, при условии сохранения этого }
{  блока.                                                }
{                                                        }
{********************************************************}

unit pyAPI;

interface

uses
 Python, Windows, dialog, SysUtils;

const
 METH_VARARGS  = $0001;
type
 TMethodArray = array[ 0 .. 16000 ] of PyMethodDef;
 PMethodArray = ^TMethodArray;

 TFuncArray = array[ 0 .. 16000 ] of PPyObject;
 TFuncNameArray = array[ 0 .. 16000 ] of PChar;

 TPyMethods = class
 private
   FMethods              : PPyMethodDef;
   FMethodsCount         : Integer;
   FAllocatedMethodCount : Integer;
   FModuleName           : PChar;
   FModuleDoc            : PChar;

   function GetMethod( Index : Integer ) : PPyMethodDef;

 public
   constructor Create(ModuleName, ModuleDoc : PChar);
   destructor Destroy; override;

   function AddMethod( AMethodName : PChar;
                       AMethod  : PyCFunction;
                       ADocString : PChar ) : PPyMethodDef;
   procedure Py_InitModule;

 end;

 TPyScript = class
 private
   FpyName   : PPyObject;
   FpyModule : PPyObject;
   FpyDict   : PPyObject;
 public
   constructor Create(ScriptName:PChar);

   function GetPyModule : PPyObject;
 end;

 TPyFunction = class
 private
   FpyModule           : PPyObject;
   FFuncCount          : Integer;
   FAllocatedFuncCount : Integer;
   FFuncs              : TFuncArray;
   FFuncNames          : TFuncNameArray;
 public
   constructor Create(pyModule : PPyObject);

   function AddFunc( FuncName:PChar ) : PPyObject;
   function GetFuncByName(FuncName:PChar) : PPyObject;
   function CallFuncByName(FuncName:PChar; FuncArgs: PPyObject) : PPyObject;

 end;

Procedure InitPython;
Procedure ExecPythonScript;
Procedure FreePython;

var
 DllHeader     : HModule;
 pyScript      : TPyScript;
 PyMethods     : TPyMethods;
 PyFunction    : TPyFunction;
 PyModule      : PPyObject;

implementation

//====================================================================

constructor TPyMethods.Create(ModuleName, ModuleDoc : PChar);
begin

   FAllocatedMethodCount:=PYT_METHOD_BUFFER_INCREASE;
   FMethodsCount:=0;
   FMethods:=PPyMethodDef(AllocMem(SizeOf(PyMethodDef)*(FAllocatedMethodCount+1)));
   FModuleName:=ModuleName;
   FModuleDoc:=ModuleDoc;
end;

//--------------------------------------------------------------------

destructor TPyMethods.Destroy;
begin
 if Assigned(FMethods) then
 begin
   FMethods := nil;
 end;
 inherited;
end;

//--------------------------------------------------------------------

function TPyMethods.GetMethod( Index : Integer ) : PPyMethodDef;
begin
 Result := @( PMethodArray(FMethods)^[Index] );
end;

function TPyMethods.AddMethod( AMethodName : PChar;
                              AMethod  : PyCFunction;
                              ADocString : PChar ) : PPyMethodDef;
var
 MethodPtr : PPyMethodDef;
begin
 Inc( FAllocatedMethodCount, PYT_METHOD_BUFFER_INCREASE );
 ReAllocMem( FMethods, SizeOf(PyMethodDef)*(FAllocatedMethodCount+1));
 MethodPtr :=@(PMethodArray(FMethods)^[FMethodsCount+1]);
 FillChar( MethodPtr^,SizeOf(PyMethodDef)*PYT_METHOD_BUFFER_INCREASE,0);
 Result:=GetMethod(FMethodsCount);
 Result^.ml_meth:=AMethod;
 Result^.ml_name:=AMethodName;
 Result^.ml_doc:=ADocString;
 Result^.ml_flags := METH_VARARGS;
 Inc(FMethodsCount);
end;

//--------------------------------------------------------------------

procedure TPyMethods.Py_InitModule;
begin
 Py_InitModule4(FModuleName, PyMethods.FMethods,FModuleDoc,nil,1012);
end;

//====================================================================

constructor TPyScript.Create(ScriptName:PChar);
begin
 FpyName   := PyString_FromString(ScriptName);

 FpyModule := PyImport_Import(FpyName);
 Py_DECREF(FpyName);

 FpyDict := PyModule_GetDict(FpyModule);
end;

//--------------------------------------------------------------------

function TPyScript.GetPyModule : PPyObject;
begin
 Result:=FpyModule;
end;


 
SkyRanger ©   (2005-11-23 03:55) [1]


//====================================================================

constructor TPyFunction.Create(pyModule : PPyObject);
begin
   FpyModule:=pyModule;
end;

//--------------------------------------------------------------------

function TPyFunction.AddFunc(FuncName:PChar) : PPyObject;
var
 FuncPtr : PPyMethodDef;
begin
 FFuncNames[FFuncCount]:=FuncName;
 FFuncs[FFuncCount]:=PyObject_GetAttrString(FpyModule,FuncName);
 Inc(FFuncCount);
end;

//--------------------------------------------------------------------

function TPyFunction.GetFuncByName(FuncName:PChar) : PPyObject;
var
 I : Integer;
begin
 for I:=0 to FFuncCount-1 do
   if FFuncNames[I] = FuncName then
     Result := FFuncs[I];
end;

//--------------------------------------------------------------------

function TPyFunction.CallFuncByName(FuncName:PChar; FuncArgs: PPyObject) : PPyObject;
begin
 Result:=PyObject_CallObject(GetFuncByName(FuncName), FuncArgs);
end;

//====================================================================

function Py_Show( self, args : PPyObject ) : PPyObject; cdecl;
begin
     ShowMessage( "args of Show: "+PyString_AsString(PyObject_Str(args)) );
     Result := Py_None;
end;

//====================================================================

Procedure InitPython;
var
 ScriptName : PChar;
 FuncName   : String;
 S          : String;
 pValue     : PPyObject;
begin
 ScriptName:="script";
 FuncName := "multiply";

 PythonInit;

 PyMethods := TPyMethods.Create("Show", "Module Documentation");

 PyMethods.AddMethod("show",Py_Show,"Proc Doc");
 PyMethods.AddMethod("show1",Py_Show,"Proc Doc");
 PyMethods.AddMethod("show2",Py_Show,"Proc Doc");
 PyMethods.AddMethod("show3",Py_Show,"Proc Doc");
 PyMethods.AddMethod("show4",Py_Show,"Proc Doc");

 PyMethods.Py_InitModule;

 PyScript := TPyScript.Create(ScriptName);

 PyModule:=PyScript.GetPyModule;

 PyFunction:= TPyFunction.Create(PyModule);
 PyFunction.AddFunc("OnPaint");
 PyFunction.AddFunc("OnInit");
 PyFunction.AddFunc("OnShow");
 PyFunction.CallFuncByName("OnInit",nil);
 PyFunction.CallFuncByName("OnShow",nil);
 pValue  := PyFunction.CallFuncByName("OnPaint",nil);
 Str(PyInt_AsLong(pValue),S);
 Py_DECREF(pValue);
 ShowMessage( S );
end;

//====================================================================

Procedure ExecPythonScript;
var
 S          : String;
 pValue     : PPyObject;
begin
 pValue  := PyFunction.CallFuncByName("OnPaint",nil);
 Str(PyInt_AsLong(pValue),S);
 Py_DECREF(pValue);
 ShowMessage( S );
end;

//====================================================================

Procedure FreePython;
begin
 PyMethods.Free;
 PyScript.Free;
 PyFunction.Free;
 PythonFree;
end;

//====================================================================

end.


Вот скрипт на питоне который используется для тестирования:


import Show

print Show.__doc__
print Show.__name__

a=3
b=1
print a,b

#Show.show(2,2,2)
#Show.show4(12,12,12)

def OnInit():    
Show.show(1,2,3)
a=3
b=3

def OnShow():    
Show.show(10,20,30)
a=3
b=3
print "111 Will compute", a, "times", b

def OnPaint():    
Show.show(100,200,300)
return 4

Все бы хорошо, если бы не одно НО:

Если я вызываю просто

InitPython;
FreePython;

Все работает как надо, все вызывается и т.д.

Если же я сделаю так:
InitPython;
ExecPythonScript;
FreePython;

Получаю Access Violation на вызове функции:
pValue  := PyFunction.CallFuncByName("OnPaint",nil);

При том даже если я удалю подобный вызов из InitPython;ничего не изменяется :(

По-идее все должно работать, но на практике возникают непонятные проблемы... :(

Скрипт Python.pas вы можете скачать здесь - http://skyr.newmail.ru/Python.pas. Это аналог python.h - импорт функций из .dll питона.


 
Digitman ©   (2005-11-23 08:45) [2]

что показала пошаговая трассировка ?


 
alex_*** ©   (2005-11-23 09:28) [3]

и ты предлагаешь скачать это себе и заняться отладкой?


 
SkyRanger ©   (2005-11-23 09:31) [4]

Ничего!

на function TPyFunction.CallFuncByName(FuncName:PChar; FuncArgs: PPyObject) :
при выполенении:
Result:=PyObject_CallObject(GetFuncByName(FuncName), FuncArgs);

ACCESS VIOLATION и все.

Причем все экземпляры классов никуда не деваются и не изменяются вProcedure ExecPythonScript;
вызов:
pValue  := PyFunction.CallFuncByName("OnPaint",nil);

А тем не менее ошибка появляется...

Причем вызов из процедуры в которой создается экземпляр класса не дает ошибок. Только пи вызове из любого места появляется такая вот ошибка :(

Вот почему так понять не могу...


 
SkyRanger ©   (2005-11-23 09:32) [5]

alex_*** я ничего не предлагаю, а задаю вопрос и надеюсь на ответ, так как я практически все сделал правильно, иначе вообще бы не работало.


 
Digitman ©   (2005-11-23 09:39) [6]


> при выполенении:
> Result:=PyObject_CallObject(GetFuncByName(FuncName), FuncArgs);
>
>
> ACCESS VIOLATION и все.


и что ? "внутренности" этого вызова (GetFuncByName) пошагово разве нельзя пройти ?


 
SkyRanger ©   (2005-11-23 09:44) [7]

Ого...
Очень интересно... По непонятной причине не проходит сравнение на первый взгляд двух одинаковый строк в этой пресловутой функции... Очень странно. Ща буду искать де косяк. У меня такое первый раз...


 
alex_*** ©   (2005-11-23 09:44) [8]

в GetFuncByName сравниваешь указатели, а не содержимое строки. Зачем деражать в TFuncNameArray PChar, не проще string? Посмотри, отрабатывает GetFuncByName(FuncName), или сыпется в нем


 
ЮЮ ©   (2005-11-23 09:44) [9]

А что за зверь такой PyObject_CallObject?


 
alex_*** ©   (2005-11-23 09:46) [10]

с полями типа PChar вообще поосторожней. Я бы заменил поля/типы по возможности с PChar на string


 
SkyRanger ©   (2005-11-23 09:47) [11]

Мдааа...
Маразм крепчал.. Это же PChar и как я понял их низя как простые строки сранивать...

function TPyFunction.GetFuncByName(FuncName:PChar) : PPyObject;
var
I : Integer;
begin
for I:=0 to FFuncCount-1 do
  if String(FFuncNames[I]) = String(FuncName) then
    Result := FFuncs[I];
end;

Теперь вроде работает...
Спасибо всем...


 
SkyRanger ©   (2005-11-23 09:50) [12]

>с полями типа PChar вообще поосторожней. Я бы заменил поля/типы по >возможности с PChar на string

Низя я работаю с функциями импортируемыми из DLL, которая написанна на C++ и чтобы потом не ломать голову почему не работает приходится юзать PChar.

Спасибо за подсказку буду внимательнее...


 
SkyRanger ©   (2005-11-23 09:51) [13]

ЮЮ ©

Если очень интересно то смотри модуль:

http://skyr.newmail.ru/Python.pas

Либо доку по Python - www.python.org


 
alex_*** ©   (2005-11-23 09:52) [14]

вот скажи, зачем ты строки в виде PChar хранишь? Потом в один прекрасный момент начнешь глюки ловить. и уж лучше сравнивать через StrCmp (не помню точно имя, дельфи не стоит)


 
alex_*** ©   (2005-11-23 09:54) [15]

[12] - ну и отлепись чуть от чужой ДЛЛ. скопируй себе строки и работай со своей копией


 
SkyRanger ©   (2005-11-23 10:04) [16]

Всмысле отлепися? исходников на Дельфи нет и не будет. Это интерпритатор питона + куча полезных вещей...


 
alex_*** ©   (2005-11-23 10:10) [17]

в смысле чем меньше зависишь от чужого кода, тем лучше. Если висеть на указателях, данные по которым находятся в чужом коде, то неизвестно что там с ними может произойти. Лучше по возможности работать со своей копией.


 
jack128 ©   (2005-11-23 10:30) [18]

SkyRanger ©   (23.11.05 9:50) [12]
Низя я работаю с функциями импортируемыми из DLL, которая написанна на C++ и чтобы потом не ломать голову почему не работает приходится юзать PChar

LOL.  А те не все равно на чем ломать голову - почему не работает при использовании PChar или почему не работает при использовании string ??

И вообще - это полная чушь, что если ипользует dll, писанные С(++), то нельзя использовать string.


 
TUser ©   (2005-11-23 10:40) [19]

А чего такого можно сделать на питоне, чего нельзя на паскале? Чем вызвана необходимость использования всяких экзотических движков?


 
SkyRanger ©   (2005-11-24 01:05) [20]

Например писать скрипт управления сценой 3d движка, описание интерфейса программы на этом движке. Воообще можно сделать много чего интересного. И самое главное не придется пересобирать ядро. Достаточно добавить код в скрипт.

Все очень просто есть возможность вызова как функций определенных в скрипте питона, так и функций определенных в самом движке и импортированых из него посредством специально объявленного модуля...


 
alex_*** ©   (2005-11-24 09:39) [21]

Ну то что можно не перекомпилять ядро это прикольно, конечно, а быстродействие не страдает?


 
SkyRanger ©   (2005-11-25 03:36) [22]

Нет, а с чего бы, я же не выполняю кучу операций с плавающей точкой или сортировки, просто классы для интерфейса, кнопочек и окошечек всяких. Потом событие OnPaint при отрисовке чтобы он знал что вызывать. Все хранится в ядре из скрипта вызываются толко функции, так что быстродействие не страдает. Питон сам по себе довольно шустрый...



Страницы: 1 вся ветка

Форум: "Начинающим";
Текущий архив: 2005.12.11;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.53 MB
Время: 0.04 c
11-1111900058
серый мЫш
2005-03-27 09:07
2005.12.11
XLGrid: Редактирование.


2-1132550552
Mamur
2005-11-21 08:22
2005.12.11
Обращение из папки которой запускается


2-1132223758
DeeperMD
2005-11-17 13:35
2005.12.11
TComPort - ComDataPacket


4-1129121344
Mamed
2005-10-12 16:49
2005.12.11
Open file


14-1132296191
Ega23
2005-11-18 09:43
2005.12.11
С днем рождения! 18 ноября





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский