Перевод кода из Delphi в FPC

Вопросы программирования на Free Pascal, использования компилятора и утилит.

Модератор: Модераторы

Перевод кода из Delphi в FPC

Сообщение SkyRanger » 05.04.2007 14:31:21

Возникла такая проблема.
Решил я свой проект перевести на 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 у меня не очень, так сказать, развита :)
SkyRanger
новенький
 
Сообщения: 10
Зарегистрирован: 13.07.2006 12:55:36
Откуда: Магадан

Сообщение Sergei I. Gorelkin » 05.04.2007 18:34:52

Смотрю, смотрю, и совершенно не понимаю, как бы это помягче сказать, философской идеи существования этого класса. Хранить адреса ф-ций из динамически подгружаемой DLL? Или для приведения Сишной функции с неопределенным числом переменных к конструкции "array of Pointer"?

Что мешает написать вот так:
Код: Выделить всё
var
  DLL_PyArg_Parse: function(args:PPyObject; format: PChar; argp: array of Pointer): Integer; cdecl;

...
// инициализируем
Pointer(DLL_PyArg_Parse) := GetProcAddress(...);
...
// пользуемся
DLL_PyArg_Parse(args, 'ddss', [@x, @y]);


:?:

Еще есть модификатор varargs. Т.е. вместо этих 'array of Pointer' объявляем ф-цию вот так:

Код: Выделить всё
function(args: PPyObject; format: PChar): Integer; cdecl; varargs;

Это, кстати, поддерживается и в Delphi6 и выше.
Но тогда во всех вызовах этой ф-ции придется убирать квадратные скобки.

Наконец, вместо проблемного call eax можно попробовать call dword ptr eax.
Аватара пользователя
Sergei I. Gorelkin
энтузиаст
 
Сообщения: 1406
Зарегистрирован: 24.07.2005 14:40:41
Откуда: Зеленоград

Сообщение bw » 05.04.2007 18:49:53

Необходима для:
Или для приведения Сишной функции с неопределенным числом переменных к конструкции "array of Pointer"?
Незнал про varargs, спасибо, буду иметь ввиду.

..bw
Аватара пользователя
bw
постоялец
 
Сообщения: 359
Зарегистрирован: 01.12.2005 11:36:23
Откуда: Усть-Илимск

Сообщение SkyRanger » 06.04.2007 11:39:41

Помогло! Спасибо! Заюзал varargs и все норм :)
SkyRanger
новенький
 
Сообщения: 10
Зарегистрирован: 13.07.2006 12:55:36
Откуда: Магадан


Вернуться в Free Pascal Compiler

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 3

Рейтинг@Mail.ru