Текущий архив: 2005.12.11;
Скачать: CL | DM;
ВнизСтранные проблемы с классами Найти похожие ветки
← →
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;
Скачать: CL | DM;
Память: 0.53 MB
Время: 0.094 c