FPC LUA

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

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

Re: FPC LUA

Сообщение vitya007 » 03.11.2016 01:26:57

Я думаю плохая затея это все делать. :(

Код: Выделить всё
program test;
{$H+}

{$LINKLIB liblua53.a}

type
   Plua_State = Pointer;

function luaL_newstate(): Plua_State; cdecl; external;
procedure lua_close(L: Plua_State); cdecl; external;

procedure Main;
var
   L: Plua_State;
begin
   L := luaL_newstate();
   lua_close(L);
end;

begin
   Main;
   Write('Exit..');
   Readln();
end.


Код: Выделить всё
test.pas(22,16) Error: Undefined symbol: __imp___iob
test.pas(22,16) Error: Undefined symbol: ___chkstk_ms
test.pas(22,16) Error: Undefined symbol: __errno
test.pas(22,16) Error: Undefined symbol: _strerror
test.pas(22,16) Error: Undefined symbol: _fread
test.pas(22,16) Error: Undefined symbol: __filbuf
test.pas(22,16) Error: Undefined symbol: _realloc
test.pas(22,16) Error: Undefined symbol: _free
test.pas(22,16) Error: Undefined symbol: ___mingw_vfprintf
test.pas(22,16) Error: Undefined symbol: _fflush
test.pas(22,16) Error: Undefined symbol: _memcpy
test.pas(22,16) Error: Undefined symbol: _strlen
test.pas(22,16) Error: Undefined symbol: _fopen
test.pas(22,16) Error: Undefined symbol: _fclose
test.pas(22,16) Error: Undefined symbol: _freopen
test.pas(22,16) Error: Undefined symbol: _strcmp
test.pas(22,16) Error: Undefined symbol: _strstr
test.pas(22,16) Error: Undefined symbol: _time
test.pas(22,16) Error: Undefined symbol: _strchr
test.pas(22,16) Error: Undefined symbol: _strtod
test.pas(22,16) Error: Undefined symbol: _localeconv
test.pas(22,16) Error: Undefined symbol: _ldexp
test.pas(22,16) Error: Undefined symbol: ___mingw_vsprintf
test.pas(22,16) Error: Undefined symbol: _pow
test.pas(22,16) Error: Undefined symbol: _floor
test.pas(22,16) Error: Undefined symbol: _fmod
test.pas(22,16) Error: Undefined symbol: _strpbrk
test.pas(22,16) Error: Undefined symbol: _strspn
test.pas(22,16) Error: Undefined symbol: _frexp
test.pas(22,16) Error: Undefined symbol: _memcmp
test.pas(22,16) Error: Undefined symbol: _longjmp
test.pas(22,16) Error: Undefined symbol: _abort
test.pas(22,16) Error: Undefined symbol: __setjmp
test.pas(22,16) Error: Undefined symbol: ___divdi3
test.pas(22,16) Error: Undefined symbol: ___moddi3
test.pas(22,16) Error: Undefined symbol: _strcoll
test.pas(22,16) Fatal: There were 36 errors compiling module, stopping
vitya007
новенький
 
Сообщения: 32
Зарегистрирован: 10.05.2011 22:23:27

Re: FPC LUA

Сообщение скалогрыз » 03.11.2016 01:30:01

vitya007 писал(а):Я думаю плохая затея это все делать

Вот! Вот это ожидаемый результат!

теперь нужно найти C-rtl библиотеку, к которой привязана lua.
MingW ... или сейчас погуглим...

я в пути домой, так что часа через 3 отпишусь, что и как.
Пока просто оставлю этот линк здесь, там openssl статически прилинковали к FPC. Обрати внимание, что ошибки линковки точно такие же... и все были сведены на нет, и задача была решена.
скалогрыз
долгожитель
 
Сообщения: 1803
Зарегистрирован: 03.09.2008 02:36:48

Re: FPC LUA

Сообщение vitya007 » 03.11.2016 02:32:48

скалогрыз писал(а):
vitya007 писал(а):Я думаю плохая затея это все делать

Вот! Вот это ожидаемый результат!

теперь нужно найти C-rtl библиотеку, к которой привязана lua.
MingW ... или сейчас погуглим...

я в пути домой, так что часа через 3 отпишусь, что и как.
Пока просто оставлю этот линк здесь, там openssl статически прилинковали к FPC. Обрати внимание, что ошибки линковки точно такие же... и все были сведены на нет, и задача была решена.


Пока уменьшил до 5 ошибок
Код: Выделить всё
test.pas(29,16) Error: Undefined symbol: ___mingw_vfprintf
test.pas(29,16) Error: Undefined symbol: _time
test.pas(29,16) Error: Undefined symbol: _ldexp
test.pas(29,16) Error: Undefined symbol: ___mingw_vsprintf
test.pas(29,16) Error: Undefined symbol: _longjmp
test.pas(29,16) Fatal: There were 5 errors compiling module, stopping


Добавлено спустя 10 минут 45 секунд:
Код: Выделить всё
test.pas(30,16) Error: Undefined symbol: ___setusermatherr
test.pas(30,16) Error: Undefined symbol: __lock
test.pas(30,16) Error: Undefined symbol: __unlock
test.pas(30,16) Fatal: There were 3 errors compiling module, stopping


Добавлено спустя 3 минуты 20 секунд:
Код: Выделить всё
30 lines compiled, 0.1 sec, 138960 bytes code, 1316 bytes data


Добавлено спустя 6 минут 47 секунд:
Все работает. Подключил. Работает без dll. :)

Код: Выделить всё
program test;
{$H+}

{$LINKLIB liblua53.a}

{$LINKLIB liblibmingwex.a}
{$LINKLIB liblibmingw32.a}
{$LINKLIB liblibkernel32.a}
{$LINKLIB liblibmsvcrt.a}
{$LINKLIB libgcclibgcc.a}

type
   Plua_State = Pointer;

function luaL_newstate(): Plua_State; cdecl; external;
procedure lua_close(L: Plua_State); cdecl; external;

procedure Main;
var
   L: Plua_State;
begin
   L := luaL_newstate();
   
   // ...
   
   lua_close(L);
end;

begin
   Main;
   Write('Exit..');
   Readln();
end.


Изображение

Добавлено спустя 2 минуты 2 секунды:
Осталось переписать заголовки. Точно не сегодня.
vitya007
новенький
 
Сообщения: 32
Зарегистрирован: 10.05.2011 22:23:27

Re: FPC LUA

Сообщение скалогрыз » 03.11.2016 02:56:20

Ну вот. Делофто! ;)

С заголовками просто - имя библиотеки у описания функции берётся в $ifdef и всё
Последний раз редактировалось скалогрыз 03.11.2016 02:57:37, всего редактировалось 1 раз.
скалогрыз
долгожитель
 
Сообщения: 1803
Зарегистрирован: 03.09.2008 02:36:48

Re: FPC LUA

Сообщение runewalsh » 03.11.2016 02:57:32

Поздравляю, лол.

скалогрыз
>runewalsh, проблемы с Си++ исключенияи из lua модулей решил как-нибудь?
Решил правда, мысленно. В большинстве случаев сработает простой atpanic, бросающий исключение языка (оттуда даже Lua-стек раскрутить можно!), и try-lua_call()-except вместо lua_pcall:
Код: Выделить всё
{$mode objfpc} {$h+} {$coperators on}

uses
  heaptrc, SysUtils, ctypes;

const
  LuaLib                = 'lua53';

  LUA_OK                = 0;
  LUA_FIRSTPSEUDOIDX    = -1001000;
  LUA_REGISTRYINDEX     = LUA_FIRSTPSEUDOIDX;
  LUA_RIDX_GLOBALS      = 2;
  LUA_IDSIZE            = 60;

type
  lua_State       = record ptr: pointer; end;
  lua_Alloc       = function(ud: pointer; ptr: pointer; osize, nsize: csize_t): pointer; cdecl;
  lua_Chunkreader = function(L: lua_State; ud: pointer; out sz: csize_t): pcchar; cdecl;
  lua_CFunction   = function(L: lua_State): cint; cdecl;
  lua_KContext    = PtrInt;
  lua_KFunction   = function(L: lua_State; status: cint; ctx: lua_KContext): cint; cdecl;

  lua_Debug = record
    event: cint;
    name: pcchar;       // (n)
    namewhat: pcchar;   // (n) 'global', 'local', 'field', 'method'
    what: pcchar;       // (S) 'Lua', 'C', 'main', 'tail'
    source: pcchar;     // (S)
    currentline: cint;  // (l)
    linedefined: cint;  // (S)
    lastlinedefined: cint; // (S)
    nups: cuchar;       // (u) number of upvalues
    nparams: cuchar;    // (u) number of parameters
    isvararg: cschar;   // (u)
    istailcall: cuchar; // (t)
    short_src: array[0 .. LUA_IDSIZE - 1] of cchar; // (S)
    &private: pointer;
  end;

  function lua_newstate(f: lua_Alloc; ud: pointer): lua_State; cdecl; external LuaLib;
  function lua_atpanic (L: lua_State; panicf: lua_CFunction): lua_CFunction; cdecl; external LuaLib;
  procedure lua_close(L: lua_State); cdecl; external LuaLib;
  function lua_load(L: lua_State; reader: lua_Chunkreader; dt: pointer; chunkname, mode: pcchar): cint; cdecl; external LuaLib;
  procedure lua_callk(L: lua_State; nargs, nresults: cint; ctx: lua_KContext; k: lua_KFunction); cdecl; external LuaLib;
  procedure lua_settop(L: lua_State; index: cint); cdecl; external LuaLib;
  procedure lua_pushlstring(L: lua_State; s: pcchar; ls: csize_t); cdecl; external LuaLib;
  procedure lua_pushcclosure(L: lua_State; fn: lua_CFunction; n: cint); cdecl; external LuaLib;
  procedure lua_rawgeti(L: lua_State; idx, n: cint); cdecl; external LuaLib;
  procedure lua_rawset(L: lua_State; idx: cint); cdecl; external LuaLib;
  function lua_tolstring(L: lua_State; idx: cint; out len: csize_t): pcchar; cdecl; external LuaLib;
  function lua_getstack(L: lua_State; level: cint; out ar: lua_Debug): cint; cdecl; external LuaLib;
  function lua_getinfo(L: lua_State; what: pcchar; var ar: lua_Debug): cint; cdecl; external LuaLib;

  procedure lua_pushstring(L: lua_State; const s: string);
  begin
    lua_pushlstring(L, pcchar(s), length(s));
  end;

  function lua_tostring(L: lua_State; idx: cint): string;
  var
    p: pcchar;
    len: csize_t;
  begin
    p := lua_tolstring(L, idx, len);
    SetLength(result, len);
    Move(p^, pointer(result)^, len * sizeof(result[1]));
  end;

type
  TLoadStringParam = record
    s: pcchar;
    rest: size_t;
  end;

  function LuaStringReader(L: lua_State; ud: pointer; out sz: csize_t): pcchar; cdecl;
  var
    p: ^TLoadStringParam absolute ud;
  begin
    result  := pcchar(p^.s);
    sz      := p^.rest * sizeof(p^.s^);
    p^.rest := 0;
  end;

  function lua_loadstring(L: lua_State; const s, name: string): cint;
  var
    p: TLoadStringParam;
  begin
    p.s    := pcchar(s);
    p.rest := length(s);
    result := lua_load(L, @LuaStringReader, @p, pcchar(name), nil);
  end;

  procedure lua_call(L: lua_State; nargs, nresults: cint);
  begin
    lua_callk(L, nargs, nresults, 0, nil);
  end;

  procedure lua_pop(L: lua_State; n: cint);
  begin
    lua_settop(L, -1 - n);
  end;

  function LuaAllocator(ud: pointer; ptr: pointer; osize, nsize: csize_t): pointer; cdecl;
  begin
    Assert(@ud = @ud); Assert(@osize = @osize);
    result := ReallocMem(ptr, nsize);
  end;

const
  EOL = LineEnding;

  function StackTrace(L: lua_State; lim: cardinal): string;
  var
    level: cardinal;
    ar: lua_Debug;
  begin
    result := '';
    level := 0;

    while (level < lim) and (lua_getstack(L, level, ar) = 1) do
    begin
      if lua_getinfo(L, pcchar(PChar('lnS')), ar) <> 0 then
      begin
        result += EOL;
        if Assigned(ar.name) and (PChar(ar.name) <> 'C') then
          result += PChar(ar.name) + '() at ';
        result += PChar(pcchar(ar.short_src));
        if ar.currentline > 0 then result += ':' + IntToStr(ar.currentline);
      end else
        result += EOL + IntToStr(level) + ': N/A';

      inc(level);
    end;

    if result <> '' then result := EOL + 'Stack trace:' + result;
  end;

  function WrapLuaPanicToException(L: lua_State): cint; cdecl;
  begin
    raise Exception.Create(lua_tostring(L, -1) + StackTrace(L, 20));
  end;

  function LuaWriteln(L: lua_State): cint; cdecl;
  begin
    writeln(lua_tostring(L, 1));
    result := 0;
  end;

  function ErrorFromMessage(L: lua_State): Exception;
  begin
    result := Exception.Create(lua_tostring(L, -1));
    lua_pop(L, 1);
  end;

  procedure Main;
  const
    Script =
{1}  'function F()' + EOL +
      '  G()' + EOL +
      'end' + EOL +
      EOL +
{5}  'function G()' + EOL +
      '  H()' + EOL +
      'end' + EOL +
      EOL +
      'function H()' + EOL +
{10} '  CallToNonExistingFunction()' + EOL +
      'end' + EOL +
      EOL +
      'for i = 1, 10 do' + EOL +
      '  writeln("Test " .. i)' + EOL +
{15} '  if i == 8 then F() end' + EOL +
      'end' + EOL +
       EOL +
      'return "string result"';

  var
    L: lua_State;
  begin
    L := lua_newstate(@LuaAllocator, nil);
    if not Assigned(L.ptr) then
      raise Exception.Create('Not enough memory for Lua state.');
    lua_atpanic(L, @WrapLuaPanicToException);

    lua_rawgeti(L, LUA_REGISTRYINDEX, LUA_RIDX_GLOBALS);
    lua_pushstring(L, 'writeln');
    lua_pushcclosure(L, @LuaWriteln, 0);
    lua_rawset(L, -3);
    lua_pop(L, 1);

    try
      if lua_loadstring(L, Script, '=source') <> LUA_OK then
        raise ErrorFromMessage(L);

      lua_call(L, 0, 1);
      writeln(lua_tostring(L, -1));
      lua_pop(L, 1);

    finally
      lua_close(L);
    end;
  end;


begin
  try
    Main;
  except
    on E: Exception do writeln(E.Message);
  end;
end.

Код: Выделить всё
Test 1
Test 2
Test 3
Test 4
Test 5
Test 6
Test 7
Test 8
source:10: attempt to call a nil value (global 'CallToNonExistingFunction')
Stack trace:
H() at source:10
G() at source:6
F() at source:2
source:15

Главное условие при использовании этого варианта — ни в каком виде не делать «защищённый вызов» (т. к. он и превращается в longjmp при ошибке). Но кроме lua_pcall он используется и в других местах (внутренние функции luaD_rawrunprotected или luaD_pcall). Обычно ты едва ли захочешь бросать оттуда ошибки в здравом уме (например, из метаметода __gc), но вот lua_resume тоже использует, а требование отказаться от корутин уже не столь тривиально (хотя и их нечасто юзают так-то).

В общем, если ВДРУГ простой вариант неприемлем, полностью корректно будет пропатчить исходники:
— добавить в global_State обработчики вроде неких условных protf и throwf.
— передать их прямо в аргументы lua_newstate (т. к. они там уже используются) и сохранить в свежесозданном global_State.
— реализовать на стороне FPC
Код: Выделить всё
type
  lua_PFunc = procedure(L: lua_State; ud: pointer); cdecl;

function protf(f: lua_PFunc; L: lua_State; param: pointer): cint; cdecl;
begin
  try
    f(L, param);
    result := 1;
  except
    result := 0;
  end;
end;

procedure throwf(); cdecl;
begin
  raise TObject.Create;
end;
...
L := lua_newstate2(..., @protf, @throwf);
(пустое исключение никогда не вылетит наружу, необработанные Lua-ошибки прилетят в panic, с которым можно поступить как выше)

— заменить LUAI_TRY в luaD_rawrunprotected (ldo.c) на if (!g->protf(f, L, param) && lj.status == 0) lj.status = -1;
— заменить макрос LUAI_THROW(L, _) на G(L)->throwf().

Т. е. слегка расширить систему с TRY-THROW, что уже есть, но из коробки предлагает только выбор между longjmp и исключениями C++.
Аватара пользователя
runewalsh
энтузиаст
 
Сообщения: 578
Зарегистрирован: 27.04.2010 00:15:25

Re: FPC LUA

Сообщение скалогрыз » 03.11.2016 04:12:13

runewalsh писал(а):Т. е. слегка расширить систему с TRY-THROW, что уже есть

ну да, единственно верное решение
скалогрыз
долгожитель
 
Сообщения: 1803
Зарегистрирован: 03.09.2008 02:36:48

Re: FPC LUA

Сообщение Дож » 03.11.2016 05:37:30

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

Так а longjmp'ы в Lua несовместимы с longjmp'ами в FPC rtl?
Аватара пользователя
Дож
энтузиаст
 
Сообщения: 899
Зарегистрирован: 12.10.2008 16:14:47

Re: FPC LUA

Сообщение скалогрыз » 03.11.2016 08:10:52

Дож писал(а):Так а longjmp'ы в Lua несовместимы с longjmp'ами в FPC rtl?

совместимы, конечно, иначе толку от таких fpc longjump-ов.
скалогрыз
долгожитель
 
Сообщения: 1803
Зарегистрирован: 03.09.2008 02:36:48

Re: FPC LUA

Сообщение Снег Север » 03.11.2016 09:07:17

Знаю, что меня сейчас закидают тапками, но никак не могу понять - зачем к паскалевской программе цеплять посторонний скриптовый язык, если есть свой, родной, pascalscript ?
Аватара пользователя
Снег Север
долгожитель
 
Сообщения: 2993
Зарегистрирован: 27.11.2007 16:14:47

Re: FPC LUA

Сообщение скалогрыз » 03.11.2016 16:40:33

Снег Север писал(а):Знаю, что меня сейчас закидают тапками, но никак не могу понять - зачем к паскалевской программе цеплять посторонний скриптовый язык, если есть свой, родной, pascalscript ?

PascalScript, к сожалению, сирота! RemObjects, вроде как давно его бросуил в пользу Охугена. И дальнейшее его развитие, не происходит (либо идёт очень медленно).
Из личного опыта:
* нет частичных вычислений, т.е. цикл
Код: Выделить всё
while (i<length(s)) and (s[i]<>' ') do inc(i);
в PascalScript обязательно упадёт (и отлично исполнится в fpc/delphi).

* циклы - медленнные (хотя казалось бы, компилируемый код!)

И потом. Если писать программу с поддержкой скрипта, то есть шанс, что для Lua найдётся знатаков больше, чем для паскаля.
скалогрыз
долгожитель
 
Сообщения: 1803
Зарегистрирован: 03.09.2008 02:36:48

Re: FPC LUA

Сообщение runewalsh » 03.11.2016 19:55:23

Сделал как расписал, всё работает (и можно не модифицировать lua_newstate, а выделить отдельную функцию).
Аватара пользователя
runewalsh
энтузиаст
 
Сообщения: 578
Зарегистрирован: 27.04.2010 00:15:25

Re: FPC LUA

Сообщение Снег Север » 04.11.2016 11:01:15

скалогрыз писал(а):PascalScript, к сожалению, сирота! RemObjects, вроде как давно его бросуил в пользу Охугена. И дальнейшее его развитие, не происходит (либо идёт очень медленно).

Баги на гитхабе постоянно исправляются.

скалогрыз писал(а):Из личного опыта:
* нет частичных вычислений, т.е. цикл
Код: Выделить всё
while (i<length(s)) and (s[i]<>' ') do inc(i);
в PascalScript обязательно упадёт (и отлично исполнится в fpc/delphi).

Я тут чего-то сильно не понял. Только что проверил на свежаке с гитхаб (на ХЕ 10.1):
Код: Выделить всё
Program test;
var
   s: string;
   i: integer;
begin
s:='1234 56789';
i:=1;
while (i<length(s)) and (s[i]<>' ') do inc(i);
writeln(IntToStr(i));
end.

Никаких проблем.

скалогрыз писал(а):* циклы - медленнные (хотя казалось бы, компилируемый код!)

А на Lua они быстрые?
Но ИМХО, жалобы на "медленные скрипты" означают концептуально неверное их использование. Никакие ресурсоемкие вещи никогда не должны выноситься в скрипты! Скрипты - только для простых проверок, присвоений и вызовов функций (методов объектов) основной программы.

скалогрыз писал(а):И потом. Если писать программу с поддержкой скрипта, то есть шанс, что для Lua найдётся знатаков больше, чем для паскаля.
Если такой мегапроект, который привлекает сторонних разработчиков для скриптов, то можно и паскалиста найти...
Аватара пользователя
Снег Север
долгожитель
 
Сообщения: 2993
Зарегистрирован: 27.11.2007 16:14:47

Re: FPC LUA

Сообщение скалогрыз » 04.11.2016 17:53:42

Снег Север писал(а):Баги на гитхабе постоянно исправляются.

приятно удивлён! я думал он совсем помрэ!

Снег Север писал(а):Никаких проблем.

ну давай, тогда вот такой код
(что поменял:
убрал пробел из строки, и заставляю i дойди до конца, условием <=, вместо i<length(s), прошу прощения - это условие я изначально написал неправильно! ):
Код: Выделить всё
Program test;
var
   s: string;
   i: integer;
begin
s:='123456789';
i:=1;
while (i<=length(s)) and (s[i]<>' ') do inc(i);
writeln(IntToStr(i));
//writeln(i); - раскоментировать для проверки в Delphi или в FPC
end.

у меня ожидаемо падает с "Out of string range" (гитхаб версия, с fpc 2.6.4), а вот скопилированная в fpc спокойно возвращет 10.

Если это подтвердится, то вот мои соображния по-этому поводу: я не думаю, что сделать частичное исчисление в PascalScript-е сложно. НО если они его сделают, то есть шанс что код, который раньше работал, работать перестанет. (потому что люди писавшие тот код, учитывали, что паскальскрипт, не делает частичные исчисления). Может быть просто добавить опцию в компилятор - делать частичные или нет (для обратной совместимости)... но пока их там нет, я бы побоялся говорить, что PascalScript это Pascal :) ну просто потому, что даже простейший алгоритм при копи-пасте, может выдывать неожиданные ошибки (частичные исчисления были ещё в самом первом Паскале Вирта, как стандарт).

Добавлено спустя 4 минуты 26 секунд:
Снег Север писал(а):А на Lua они быстрые?

без понятия... но можно провести замеры :)

Снег Север писал(а):Но ИМХО, жалобы на "медленные скрипты" означают концептуально неверное их использование.

согласен, но тут проблема, что скрипты приходится использовать для всего :) (это концептуально проблема конторы, где я работаю)
ну и по наблюдениям, циклы получаются неожиданно медленными.
скалогрыз
долгожитель
 
Сообщения: 1803
Зарегистрирован: 03.09.2008 02:36:48

Re: FPC LUA

Сообщение Снег Север » 05.11.2016 15:23:13

скалогрыз писал(а):ну давай, тогда вот такой код

А, такое, конечно, даст ошибку. Ну так это нормально, паскальскрипт - это не полноценный компилятор. И даже в делфи/лазарус сокращенное вычисление булевских выражений включается специальным параметром в настройках.
Аватара пользователя
Снег Север
долгожитель
 
Сообщения: 2993
Зарегистрирован: 27.11.2007 16:14:47

Re: FPC LUA

Сообщение скалогрыз » 05.11.2016 18:41:42

Наверное, выключается специальным ключом?! Причём по модульно?
Кстати, что за ключик? Нагуглить не удалось.

Я думаю, что паскальскрипт - вполне себе полноценный компилятор. Но с особенностями, их нужно помнить и знать.
И код из паскаля применять с осторожностью.

В луа такого нет, тк самостоятельный язык
скалогрыз
долгожитель
 
Сообщения: 1803
Зарегистрирован: 03.09.2008 02:36:48

Пред.След.

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

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

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

Рейтинг@Mail.ru