Вопросы по использованию FFI

Столкнулись с проблемой в использовании макросов? Здесь можно получить помощь.
Post Reply
User avatar
John Doe
Бюрократ
Posts: 13807
Joined: Wed 27 Apr, 2005 20:42
Has thanked: 73 times
Been thanked: 426 times
Contact:

Вопросы по использованию FFI

Post by John Doe »

FFI — одна из стандартных библиотек luajit.
Позволяет из Lua кода вызывать внешние C-функции и использовать структуры данных C.
В данной теме задаём вопросы по использованию FFI

Заготовка для документации: viewtopic.php?f=57&t=8418&p=147610#p147610

Примеры готовых скриптов:

Предупреждение: viewtopic.php?p=147610#p147610
User avatar
John Doe
Бюрократ
Posts: 13807
Joined: Wed 27 Apr, 2005 20:42
Has thanked: 73 times
Been thanked: 426 times
Contact:

Re: Вопросы по использованию FFI

Post by John Doe »

Latest post of the previous page:

TOKEN_PRIVILEGES structure wrote:
  1. typedef struct _TOKEN_PRIVILEGES {
  2.  
  3.   DWORD               PrivilegeCount;
  4.  
  5.   LUID_AND_ATTRIBUTES Privileges[ANYSIZE_ARRAY];
  6.  
  7. } TOKEN_PRIVILEGES, *PTOKEN_PRIVILEGES;
[...]

Important The constant ANYSIZE_ARRAY is defined as 1 in the public header Winnt.h. To create this array with more than one element, you must allocate sufficient memory for the structure to take into account additional elements.
Как лучше в ffi обработать эту ситуацию с ANYSIZE_ARRAY?
  • Если следовать буквально, то как я понимаю надо вычислить размер структуры с учётом реального размера массива, выделить под неё память, и привести к нужному типу:
    1. local size = n*ffi.sizeof("LUID_AND_ATTRIBUTES") + ffi.sizeof("DWORD")
    2.  
    3. local struct = ffi.new("char[?]",size)
    4.  
    5. struct = ffi.cast("TOKEN_PRIVILEGES *",struct)
  • С другой стороны, в ffi есть ведь специальные средства.
    1. ffi.cdef[[
    2.  
    3. typedef struct _TOKEN_PRIVILEGES {
    4.  
    5.   DWORD               PrivilegeCount;
    6.  
    7.   LUID_AND_ATTRIBUTES Privileges[?];
    8.  
    9. } TOKEN_PRIVILEGES, *PTOKEN_PRIVILEGES;
    10.  
    11. ]]
    12.  
    13.  
    14.  
    15. local struct = ffi.new("TOKEN_PRIVILEGES",n)
Работают оба способа, но второй проще, и выглядит логичней.
Я ничего не упускаю?
2useven10
Posts: 5204
Joined: Mon 07 Sep, 2009 10:40
Has thanked: 18 times
Been thanked: 310 times

Re: Вопросы по использованию FFI

Post by 2useven10 »

ffi.sizeof("TOKEN_PRIVILEGES") неизвестен, если конечно нет варианта ffi.sizeof("TOKEN_PRIVILEGES", n)
User avatar
John Doe
Бюрократ
Posts: 13807
Joined: Wed 27 Apr, 2005 20:42
Has thanked: 73 times
Been thanked: 426 times
Contact:

Re: Вопросы по использованию FFI

Post by John Doe »

В первом случае размер известен (ANYSIZE_ARRAY==1)
Во втором ffi.sizeof не используется Да и вообще, ffi.sizeof("TOKEN_PRIVILEGES") не используется ни в одном из премеров выше
User avatar
zg
zero-gravity
Posts: 6016
Joined: Tue 15 Mar, 2005 17:36
Location: riga
Been thanked: 185 times
Contact:

Re: Вопросы по использованию FFI

Post by zg »

ffi.sizeof(struct)
User avatar
John Doe
Бюрократ
Posts: 13807
Joined: Wed 27 Apr, 2005 20:42
Has thanked: 73 times
Been thanked: 426 times
Contact:

Re: Вопросы по использованию FFI

Post by John Doe »

Code: Select all

local struct = ffi.new("char[?]",size)
struct = ffi.cast("TOKEN_PRIVILEGES *",struct)
А тут похоже ошибка, выделенный ffi.new буфер может быть собран сборщиком мусора...
User avatar
John Doe
Бюрократ
Posts: 13807
Joined: Wed 27 Apr, 2005 20:42
Has thanked: 73 times
Been thanked: 426 times
Contact:

Re: Вопросы по использованию FFI

Post by John Doe »

John Doe wrote:Как лучше в ffi обработать эту ситуацию с ANYSIZE_ARRAY?
Я не просто так предлагаю это обсудить.
Невозможно переопределить уже объявленный тип, ffi не даёт.
Если будет 2 скрипта с разными определениями, то один из них поломается.

Было бы неплохо договориться о совместимом способе.
Предлагаю в качестве ANYSIZE_ARRAY всегда использовать ?.
2useven10
Posts: 5204
Joined: Mon 07 Sep, 2009 10:40
Has thanked: 18 times
Been thanked: 310 times

Re: Вопросы по использованию FFI

Post by 2useven10 »

При необходимости ничто не мешает изменить имя типа, не очень красиво, но сработает.
А так вариант "Type[?]" мне тоже кажется более логичным.
User avatar
John Doe
Бюрократ
Posts: 13807
Joined: Wed 27 Apr, 2005 20:42
Has thanked: 73 times
Been thanked: 426 times
Contact:

Re: Вопросы по использованию FFI

Post by John Doe »

2useven10 wrote:При необходимости ничто не мешает изменить имя типа, не очень красиво, но сработает.
А так вариант "Type[?]" мне тоже кажется более логичным.
Можно было бы обеспечить единообразие использования таких типов, включив их определения в winapi.lua.
(Не знаю какая у нас на этот счёт политика)

P.S.
Почитал The Old New Thing и понял что тут ошибка:
  1. local size = n*ffi.sizeof("LUID_AND_ATTRIBUTES") + ffi.sizeof("DWORD")
Правильнее так
  1. local size = (n-1)*ffi.sizeof("LUID_AND_ATTRIBUTES") + ffi.sizeof("TOKEN_PRIVILEGES")
2useven10
Posts: 5204
Joined: Mon 07 Sep, 2009 10:40
Has thanked: 18 times
Been thanked: 310 times

Re: Вопросы по использованию FFI

Post by 2useven10 »

2useven10 wrote:ffi.sizeof("TOKEN_PRIVILEGES") неизвестен, если конечно нет варианта ffi.sizeof("TOKEN_PRIVILEGES", n)
Проверил, есть такой вариант.
User avatar
John Doe
Бюрократ
Posts: 13807
Joined: Wed 27 Apr, 2005 20:42
Has thanked: 73 times
Been thanked: 426 times
Contact:

Re: Вопросы по использованию FFI

Post by John Doe »

Есть, но даже если и не было бы, в ffi.sizeof можно передать не только "имя типа", но и саму уже созданную структуру (на прошлой странице было).
2useven10
Posts: 5204
Joined: Mon 07 Sep, 2009 10:40
Has thanked: 18 times
Been thanked: 310 times

Re: Вопросы по использованию FFI

Post by 2useven10 »

John Doe wrote:Есть, но даже если и не было бы, в ffi.sizeof можно передать не только "имя типа", но и саму уже созданную структуру (на прошлой странице было).
Иногда размер нужен, а объекта нет.
Shmuel
Posts: 6819
Joined: Thu 23 Mar, 2006 21:36
Location: Israel
Has thanked: 41 times
Been thanked: 528 times

Re: Вопросы по использованию FFI

Post by Shmuel »

John Doe wrote:Можно было бы обеспечить единообразие использования таких типов, включив их определения в winapi.lua.
(Не знаю какая у нас на этот счёт политика)
По-хорошему, надо было бы farapi.lua и winapi.lua сделать модулями. Можно было бы при этом сделать и модуль winapiex (т.е. "extended"). Так как сделано сейчас - идеологически неправильно - эти файлы грузятся всегда, нужны они или не нужны.
User avatar
John Doe
Бюрократ
Posts: 13807
Joined: Wed 27 Apr, 2005 20:42
Has thanked: 73 times
Been thanked: 426 times
Contact:

Re: Вопросы по использованию FFI

Post by John Doe »

Насколько я понимаю, winapi.lua раньше содержал только то, что необходимо для LuaMacro.
Затем добавились декларации базовых типов winapi.
И всё это сейчас занимает 8 кБ, так что смысла подгружать его отдельно нет.

Если только он не раздуется в 10 раз, что врядли произойдёт.
Shmuel
Posts: 6819
Joined: Thu 23 Mar, 2006 21:36
Location: Israel
Has thanked: 41 times
Been thanked: 528 times

Re: Вопросы по использованию FFI

Post by Shmuel »

John Doe wrote:Если только он не раздуется в 10 раз, что врядли произойдёт.
farapi.lua + winapi.lua составляют вместе 78 KB. Вот вам и 10 раз налицо.
User avatar
John Doe
Бюрократ
Posts: 13807
Joined: Wed 27 Apr, 2005 20:42
Has thanked: 73 times
Been thanked: 426 times
Contact:

Re: Вопросы по использованию FFI

Post by John Doe »

farapi.lua есть смысл сделать модулем, luamacro от него не зависит.

И farapi.lua и winapi.lua можно сделать модулями, если убрать зависимость от них luamacro.
Сейчас просмотрел по-быстрому, и увидел только 3 зависимости в panelsort.lua (структура SortingPanelItem, тип HANDLE и функция StrCmpLogicalW).
User avatar
John Doe
Бюрократ
Posts: 13807
Joined: Wed 27 Apr, 2005 20:42
Has thanked: 73 times
Been thanked: 426 times
Contact:

Re: Вопросы по использованию FFI

Post by John Doe »

Shmuel wrote:Можно было бы при этом сделать и модуль winapiex (т.е. "extended").
Предвижу сложности. Возьмём такой сценарий.
1) Какой-то скрипт не использует модуль winapiex.lua, но для своих нужд определяет тип "TOKEN_PRIVILEGES"
2) Другой скрипт пытается после этого загрузить winapiex.lua, но обламывается, т.к. ffi не даёт переопределить.

И pcall в данном случае не особо поможет

P.S.
Насколько я могу судить, облом только при попытке переопределить структуры.
Post Reply

Return to “Нужна помощь”