Решил я свой проект перевести на FPC полностью. Начал с малого и постепенно подключал и изменял все новые модули. Пока не дошел до Python модуля.
Этот модуль был получен путем жестокой кастрации движка для питона от http://mmm-experts.com
У них есть класс с парой крайне важных функций: PyArg_Parse и PyArg_ParseTuple
Вот определение класса:
- Код: Выделить всё
TpyParser = class
private
DLL_PyArg_Parse: function(args: PPyObject; format: PChar {;....}):
Integer; cdecl;
DLL_PyArg_ParseTuple:
function(args: PPyObject; format: PChar {;...}):
Integer; cdecl;
public
function PyArg_Parse(args: PPyObject; format: PChar;
argp: array of Pointer): Integer; cdecl;
function PyArg_ParseTuple(args: PPyObject; format: PChar;
argp: array of Pointer): Integer; cdecl;
end;
А вот его реализация:
- Код: Выделить всё
{TpyParser}
{PyArg_Parse}
{DELPHI does the right thing here. It automatically generates
a copy of the argp on the stack}
function TpyParser.PyArg_Parse(args: PPyObject; format: PChar;
argp: array of Pointer): Integer; cdecl;
begin
{$IFDEF DELPHI6_OR_HIGHER}
Result := 0;
{ Do not optimize this to a "pure" assembler routine, because such
a routine does not copy the array arguments in the prologue code }
asm
lea edx, format
push [edx]
sub edx, TYPE PChar
push [edx]
mov eax, Self
mov eax, [eax].DLL_PyArg_Parse
call eax
pop edx
pop edx
mov Result, eax
end;
{$ELSE}
Result := DLL_PyArg_Parse(args, format);
{$ENDIF}
PyErr_Print();
end;
//====================================================================
{PyArg_ParseTuple}
function TpyParser.PyArg_ParseTuple(args: PPyObject; format: PChar;
argp: array of Pointer): Integer; cdecl;
begin
{$IFDEF DELPHI6_OR_HIGHER}
Result := 0;
{ Do not optimize this to a "pure" assembler routine, because such
a routine does not copy the array arguments in the prologue code }
asm
lea edx, format
push [edx]
sub edx, TYPE PChar
push [edx]
mov eax, Self
mov eax, [eax].DLL_PyArg_ParseTuple
call eax
pop edx
pop edx
mov Result, eax
end;
{$ELSE}
Result := DLL_PyArg_ParseTuple(args, format);
{$ENDIF}
PyErr_Print();
end;
//====================================================================
Как видно при компиляции в Д6 все работает, я проверял. При компиляции в FPC вызывается "затычка" DLL_PyArg_ParseTuple(args, format);
Это именно затычка, вот как используется функция:
- Код: Выделить всё
//====================================================================
{pyPrintString}
function pyPrintString(self, args: PPyObject): PPyObject; cdecl;
var
x, y, z: GLDouble;
Strs: PChar;
FontName: PChar;
begin
if pyParser.PyArg_ParseTuple(args, 'dddss', [@x, @y, @z, @Strs,
@FontName]) = -1 then
Result := nil
else
begin
FontsManager.PrintString(x, y, z, Strs, FontName);
end;
Py_INCREF(Py_None);
Result := Py_None;
end;
//====================================================================
т.е. должен быть третий параметр, и он функции при компиляции не в Д6 никуда не передается, соответственно имею при вызове ошибку и краш программы.
При попытке убрать {$IFDEF DELPHI6_OR_HIGHER} и использовать код, получаю ошибку в строке с :
call eax
Как правильно портировать сей код на FPC? Работа с памятью и ASM у меня не очень, так сказать, развита
