Вопросы по использованию FFI
- John Doe
- Бюрократ
- Posts: 13853
- Joined: Wed 27 Apr, 2005 20:42
- Has thanked: 73 times
- Been thanked: 428 times
- Contact:
Вопросы по использованию FFI
FFI — одна из стандартных библиотек luajit.
Позволяет из Lua кода вызывать внешние C-функции и использовать структуры данных C.
В данной теме задаём вопросы по использованию FFI
Заготовка для документации: viewtopic.php?f=57&t=8418&p=147610#p147610
Примеры готовых скриптов:
Предупреждение: viewtopic.php?p=147610#p147610
Позволяет из Lua кода вызывать внешние C-функции и использовать структуры данных C.
В данной теме задаём вопросы по использованию FFI
Заготовка для документации: viewtopic.php?f=57&t=8418&p=147610#p147610
Примеры готовых скриптов:
Предупреждение: viewtopic.php?p=147610#p147610
-
- Posts: 6834
- Joined: Thu 23 Mar, 2006 21:36
- Location: Israel
- Has thanked: 41 times
- Been thanked: 530 times
Вопросы по использованию FFI
Latest post of the previous page:
На мой взгляд, сказано исчерпывающе ("This copies the whole string plus a terminating zero-byte").
- John Doe
- Бюрократ
- Posts: 13853
- Joined: Wed 27 Apr, 2005 20:42
- Has thanked: 73 times
- Been thanked: 428 times
- Contact:
Вопросы по использованию FFI
Меня ввело в заблужнение то, что непосредственно перед этим сказано: all remaining uninitialized elements are filled with zero bytes.
А так да, не спорю.
А так да, не спорю.
- John Doe
- Бюрократ
- Posts: 13853
- Joined: Wed 27 Apr, 2005 20:42
- Has thanked: 73 times
- Been thanked: 428 times
- Contact:
Вопросы по использованию FFI
Заготовка для документации:
0. Использование ffi (помимо усвоения документации библиотеки) в целом требует определённой квалификации, понимания работы вызываемых функций, осторожного обращения с памятью, и т.п.
Ниже следуют только дополнения, описывающие особенности использования ffi в фаре
1. Любое определение, сделанное посредством
Переопределить его невозможно: будет действовать определение, сделанное первым.
1.1. Определение, сделанное в одном скрипте будет действовать для всех, поэтому важно чтобы определения были корректными.
1.2. В случае изменения определения на несовместимое потребуется перезагрузить плагин (или фар).
2. В отличии от переопределения функций, попытка переопределения констант и именованных(?) структур ещё и вызывает ошибку времени выполнения, поэтому следует оборачивать вызов в pcall:
2.1. Следует учитывать, что "переопределение" неизбежно, это вполне штатная ситуация: например при перезагрузке макросов, или при использовании определений в независимых скриптах.
3. Для удобства luamacro при старте загружает файл winapi.lua, содержащий определения типов, часто используемых в winapi.
4. ???
Работа со строками, с юникодом, передача параметра по ссылке или значению (_OUT_/_IN_ в msdn) это то, что абсолютно необходимо понимать при работе с ffi.
Прочитав тему с начала можно найти ответы на множество вопросов.
Если же вы не готовы тратить своё время на то чтобы во всём разобраться, то и начинать не стоит.
Todo: задокументировать нюансы, имеющие значение для распространённых задач:
- работа со строками, завершающий \0
- получение указателей/хэндлов, ...
- ограничение типов на 32бита: viewtopic.php?p=119951#p119951
0. Использование ffi (помимо усвоения документации библиотеки) в целом требует определённой квалификации, понимания работы вызываемых функций, осторожного обращения с памятью, и т.п.
Ниже следуют только дополнения, описывающие особенности использования ffi в фаре
1. Любое определение, сделанное посредством
ffi.cdef
, действует до конца сеанса.Переопределить его невозможно: будет действовать определение, сделанное первым.
1.1. Определение, сделанное в одном скрипте будет действовать для всех, поэтому важно чтобы определения были корректными.
1.2. В случае изменения определения на несовместимое потребуется перезагрузить плагин (или фар).
2. В отличии от переопределения функций, попытка переопределения констант и именованных(?) структур ещё и вызывает ошибку времени выполнения, поэтому следует оборачивать вызов в pcall:
2.1. Следует учитывать, что "переопределение" неизбежно, это вполне штатная ситуация: например при перезагрузке макросов, или при использовании определений в независимых скриптах.
3. Для удобства luamacro при старте загружает файл winapi.lua, содержащий определения типов, часто используемых в winapi.
4. ???
Работа со строками, с юникодом, передача параметра по ссылке или значению (_OUT_/_IN_ в msdn) это то, что абсолютно необходимо понимать при работе с ffi.
Прочитав тему с начала можно найти ответы на множество вопросов.
Если же вы не готовы тратить своё время на то чтобы во всём разобраться, то и начинать не стоит.
Todo: задокументировать нюансы, имеющие значение для распространённых задач:
- работа со строками, завершающий \0
- получение указателей/хэндлов, ...
- ограничение типов на 32бита: viewtopic.php?p=119951#p119951
Last edited by John Doe on Sat 12 May, 2018 16:50, edited 1 time in total.
-
- Posts: 6834
- Joined: Thu 23 Mar, 2006 21:36
- Location: Israel
- Has thanked: 41 times
- Been thanked: 530 times
- Smitis
- Posts: 1709
- Joined: Fri 18 Mar, 2005 12:51
- Location: Питер
- Has thanked: 23 times
- Been thanked: 55 times
Вопросы по использованию FFI
В подавляющем большинстве случаев достаточно убрать имя структуры
Code: Select all
ffi.cdef [[
typedef struct { // _CONSOLE_SELECTION_INFO
DWORD dwFlags;
COORD dwSelectionAnchor;
SMALL_RECT srSelection;
} CONSOLE_SELECTION_INFO, *PCONSOLE_SELECTION_INFO;
]]
Разум когда-нибудь победит.
- John Doe
- Бюрократ
- Posts: 13853
- Joined: Wed 27 Apr, 2005 20:42
- Has thanked: 73 times
- Been thanked: 428 times
- Contact:
Вопросы по использованию FFI
Да, выше по теме было.
Но имя структуры используется в сообщениях об ошибках, поэтому я бы не стал его комментировать, safe_def предпочтительнее.
На самом деле любая попытка переопределения это действительно ошибка, и даже странно что её нет с безымянными структурами и функциями.
В идеале было бы, если бы повторное определение проверялось на соответствие с имеющимся, и ошибка выдавалась бы в случае несовместимых определений.
Но нет, повторные просто проглатываются, не выдавая ошибок, но и не переопределяя.
- buniak_a_h
- Posts: 4262
- Joined: Sat 20 Apr, 2013 00:17
- Location: Санкт-Петробад
- Has thanked: 222 times
- Been thanked: 644 times
- Contact:
Вопросы по использованию FFI
Написал микроскрипт:
Code: Select all
local winapi=require"winapi"
local ffi = require("ffi")
far.Show('qq')
Code: Select all
╔════════════════════════════════════════════════════ LuaMacro ═════════════════════════════════════════════════════╗
║ ...ta\Roaming\Far Manager\Profile\Macros\modules\winapi.lua:319: attempt to redefine '_UNICODE_STRING' at line 52 ║
║ stack traceback: ║
║ [C]: in function 'require' ║
║ \\?\D:\ttt\www.lua:1: in main chunk ║
╟───────────────────────────────────────────────────────────────────────────────────────────────────────────────────╢
║ { OK } ║
╚═══════════════════════════════════════════════════════════════════════════════════════════════════════════════════╝
- buniak_a_h
- Posts: 4262
- Joined: Sat 20 Apr, 2013 00:17
- Location: Санкт-Петробад
- Has thanked: 222 times
- Been thanked: 644 times
- Contact:
Вопросы по использованию FFI
Господа! Помогите, кто может!
Есть маленький скрипт: Описывается интерфейс к двум функциям из WINAPI: MessageBoxA и CopyFileA. У обеих функций есть параметры типа LPCTSTR (строка в кодировке ASCII).
Вызов MessageBoxA проходит ожидаемо (выводятся обе строки - в заголовке и на форм) А вот при вызове CopyFileA почему-то возникает ошибка:
При том, что параметры описаны абсолютно одинаково, аргумент-строка передается одна и та же...
Что я делаю не так? И как надо? Уже голову сломал...
Есть маленький скрипт: Описывается интерфейс к двум функциям из WINAPI: MessageBoxA и CopyFileA. У обеих функций есть параметры типа LPCTSTR (строка в кодировке ASCII).
Вызов MessageBoxA проходит ожидаемо (выводятся обе строки - в заголовке и на форм) А вот при вызове CopyFileA почему-то возникает ошибка:
bad argument #1 to '?' (cannot convert 'string' to 'const unsigned short *')
При том, что параметры описаны абсолютно одинаково, аргумент-строка передается одна и та же...
Что я делаю не так? И как надо? Уже голову сломал...
Вопросы по использованию FFI
Если вы используете неюникодные ф-и (почему?), то описывайте строковые аргументы как LPCSTR.
LPCTSTR - условный тип, который в зависимости от дефайнов считается либо LPCSTR, либо в LPCWSTR.
Видимо дефайны у вас и у ffi разные.
LPCTSTR - условный тип, который в зависимости от дефайнов считается либо LPCSTR, либо в LPCWSTR.
Видимо дефайны у вас и у ffi разные.
Вопросы по использованию FFI
Лучше пользоваться юникодными вариантами ф-й -- MessgeBoxW, CopyFileW и соответственно LPCWSTR.
Лишнее преобразование из юникода при этом надо выкинуть.
Юникодные строки должны закачиваться юникодным нулём. Lua сам такого не делает, поэтому
приходится в конце строки явно добавлять свой ноль -- "filename\0".
Лишнее преобразование из юникода при этом надо выкинуть.
Юникодные строки должны закачиваться юникодным нулём. Lua сам такого не делает, поэтому
приходится в конце строки явно добавлять свой ноль -- "filename\0".
-
- Posts: 6834
- Joined: Thu 23 Mar, 2006 21:36
- Location: Israel
- Has thanked: 41 times
- Been thanked: 530 times
Вопросы по использованию FFI
Аналогичный вопрос уже задавался в данной ветке.
Ответ:
pcall(require,"winapi")
Надо в определениях заменить LPCTSTR на const char*
И как верно заметили выше, желательно работать с юникодными версиями функций Windows API. Зачем возвращаться к давно преодолённым ограничениям ASCII.
Last edited by Shmuel on Fri 11 May, 2018 06:58, edited 1 time in total.
Вопросы по использованию FFI
у меня работает. (немного поправил)
Last edited by 2useven10 on Fri 11 May, 2018 12:19, edited 2 times in total.
- buniak_a_h
- Posts: 4262
- Joined: Sat 20 Apr, 2013 00:17
- Location: Санкт-Петробад
- Has thanked: 222 times
- Been thanked: 644 times
- Contact:
Вопросы по использованию FFI
Это - первое, что я попробовал . Это - не помогает...Shmuel wrote: ↑Fri 11 May, 2018 06:54Аналогичный вопрос уже задавался в данной ветке.
Ответ:pcall(require,"winapi")
Это если б мне надо было, чтоб заработало. Но Вы пишете, что require"winapi" нужно для получения диагностики. «Ошибка сразу и вылезла». Вот она и вылезла, при том, что своих определений я не давал...
Впрочем, вопрос академический. У кого-то ошибка... Я просто убрал require"winapi".Надо в определениях заменить LPCTSTR на const char*
Пример с MessageBoxA взят из FFI Library. Просто я ничего не понимаю в кодировках, сделал как попугай, по образу и подобию примера. А там почему-то "A"-вариант.
- buniak_a_h
- Posts: 4262
- Joined: Sat 20 Apr, 2013 00:17
- Location: Санкт-Петробад
- Has thanked: 222 times
- Been thanked: 644 times
- Contact:
Вопросы по использованию FFI
У меня - нет. Т.е. ошибки не выдаёт, но и файл не копирует. Просто уничтожает. Может, дело в том, что \0 добавлен в inPath, а outPath получен дописыванием к InPath ещё чего-то (за финальным нулём!)?
- buniak_a_h
- Posts: 4262
- Joined: Sat 20 Apr, 2013 00:17
- Location: Санкт-Петробад
- Has thanked: 222 times
- Been thanked: 644 times
- Contact:
Вопросы по использованию FFI
Добавочка.
Если из inPath сначала убрать .. '\0', а затем отдельной строкой написать
inPath = inPath .. '\0'
то вылет следующий:
Code: Select all
╔══════════════════════════ Exception occurred ══════════════════════════╗
║ Exception: 0xC0000005 - EXCEPTION_ACCESS_VIOLATION ║
║ Details: Memory at FFFFFFFFFFFFFFFE could not be read ║
║ Address: 0x7FFCE9EE5F0F - KERNELBASE.dll!BasepCopyFileCallback ║
║ Source: ║
║ Function: OpenW ║
║ Module: :\Program Files\Far Manager\Plugins\LuaMacro\LuaMacro.dll ║
╟────────────────────────────────────────────────────────────────────────╢
║ { Unload plugin } [ Stack ] [ Minidump ] [ Ignore ] ║
╚════════════════════════════════════════════════════════════════════════╝