Page 8 of 20

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

Posted: Tue 21 May, 2013 20:20
by John Doe
FFI — одна из стандартных библиотек luajit.
Позволяет из Lua кода вызывать внешние C-функции и использовать структуры данных C.
В данной теме задаём вопросы по использованию FFI

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

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

Предупреждение: viewtopic.php?p=147610#p147610

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

Posted: Thu 19 Jun, 2014 15:34
by Shmuel

Latest post of the previous page:

John Doe wrote:Сегодня совместим, а завтра мы добавили в поставку новые структуры, и стал несовместим. Нехорошо.
Это не проблема, если сторонние скрипты будут вызывать require "winapi" перед своими ffi-определениями. Ошибка сразу и вылезет.

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

Posted: Thu 19 Jun, 2014 20:01
by John Doe
Не вылезет, ведь свои определения завёрнуты в pcall.

Но да, если обязать всех делать require ("winapi") до собственных деклараций, то это поможет решить проблему. Административно.

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

Posted: Thu 19 Jun, 2014 20:19
by Shmuel
Ситуация на данный момент мало чем отличается от всего, что вы описываете.
-- Два разных скрипта могут определить конфликтующие декларации.
-- Скрипт может завернуть свою конфликтующую с фаровской декларацию в pcall, и это пройдёт незамеченным.
-- "Административно" - никто не запрещает пользоваться исключительно глобальными переменными с короткими именами, никто не запрещает сделать _G.far=45 и т.д.

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

Posted: Thu 19 Jun, 2014 20:34
by John Doe
Shmuel wrote:-- Два разных скрипта могут определить конфликтующие декларации.
Это у нас уже принято решать обёртками вокруг ffi.cdef.
Реальная проблема будет только если декларации окажутся несовместимыми. Это возможно, но сравнительно маловероятно.
Shmuel wrote:-- Скрипт может завернуть свою конфликтующую с фаровской декларацию в pcall, и это пройдёт незамеченным.
Это вообще крайне маловероятно, в фаре только winapi/farapi, и пользовательская декларация может оказаться несовместимой разве что в результате ошибки пользователя.
Shmuel wrote:И т.д. и т.п.
Предлагаю рассмотреть поимённо.
Shmuel wrote:Ситуация на данный момент мало чем отличается от всего, что вы описываете.
На данный момент фаровские определения грузятся первыми.
Из этого следует, что в случае конфликта пострадает только сам конфликтующий скрипт.

Если же фаровские определения станут модулями, то в случае конфликта наоборот, пострадают все прочие скрипты, честно использующие require в начале.
Причём сообщение об ошибке вообще не будет указывать на реальный источник конфликта.

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

Posted: Thu 19 Jun, 2014 20:38
by Shmuel
1. Отредактировал чуть сообщение выше
2. Устал, больше в подобные дискуссии постараюсь не ввязываться
3. Сделаю, как сочту нужным

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

Posted: Thu 19 Jun, 2014 21:18
by John Doe
Вот ещё информация к размышлению:
ffi.cdef выдаёт ошибку в случае попытки повторного объявления структуры с тем же именем типа.
Но если объявить структуру с другим именем типа (struct NewName {...}), или без имени (struct {...}), то никаких сообщений об ошибке не будет.
Может быть это стоит использовать? Ведь по факту в winapi не используются имена типов структур, а типы определяются typedef:

Есть ещё один момент: ошибка не выдаётся, но и переопределения никакого не происходит.
Пример:

Как бы там ни было, используя в typedef "безымянные" структуры, можно убрать обёртки вокруг ffi.cdef.
(Только для typedef, но для winapi этого в большинстве случаев кажется достаточно.)

Update
Имена типов структур используются в сообщениях об ошибках,

Code: Select all

C:\APPs\Far3\Profile\Macros\scripts\sample.lua:31: cannot convert 'number' to 'struct 2785'

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

Posted: Sat 25 Oct, 2014 21:37
by fml2
Я тут в одном макро, написанном на Lua использованием ffi, увидел следующее:

В объявлении функции с суффиксом "W" (ReadConsoleOutputCharacterW) для строкового параметра используется "макровская" запись с T: LP[u]T[/u]STR lpCharacter. Кроме того, далее в тексте используется тип wchar_t.

Вопрос: надежно ли использование "Т" в объявлении? Т.е. можно ли полагаться на то, что FFI будет все "компилировать" так, как будто используется уникод? Или лучше писать "LPWSTR"?

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

Posted: Sat 25 Oct, 2014 22:19
by zg
ffi понимает только базовые типы. LPTSTR — точно в их число не входит. значит он где-то определён. можно ли на это полагаться? не знаю. я лично не полагаюсь и все типы привожу к базовым.

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

Posted: Sun 26 Oct, 2014 07:36
by fml2
Ага! Вот оно откуда берется! А я удивлялся, откуда FFI знает все эти LPSTR и DWORD. Включение туда также и имен с T считаю разумным, т.к. это позволяет копировать объявления функций прямо со страничек MSDN. Может, еще следующее включить (если это возможно):

- WINAPI
- _In_, _In_opt_, _Inout_ и т.д.
- LPSECURITY_ATTRIBUTES
- LPOVERLAPPED

Тогда бы можно было копировать все определения прямо со страничек MSDN без каких-либо правок.

И еще какую-нибудь функцию для простого преобразования строк Lua в строки/объекты, пригодные для вызовов WINAPI, и обратно. А то я смотрю, тут даже "киты" кустарничают.

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

Posted: Sun 26 Oct, 2014 14:01
by John Doe
- WINAPI
- _In_, _In_opt_, _Inout_ и т.д.
Невозможно, ffi макросы не понимает.
LPSECURITY_ATTRIBUTES
Да, в winapi.lua сейчас определяется SECURITY_ATTRIBUTES, вполне разумно добавить туда же и производные типы.
LPOVERLAPPED
А тут не уверен (так ведь можно добавлять бесконечно).
В настоящий момент в winapi.lua в основном представлены типы отсюда.

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

Posted: Sun 26 Oct, 2014 18:40
by fml2
John Doe wrote:А тут не уверен (так ведь можно добавлять бесконечно).
LPOVERLAPPED используется как параметр в функции ReadFile (и WriteFile). Думаю, что т.к. эти функции "довольно базовые" (или нет?), то хорошо было бы, чтобы типы их параметеров регистрировались автоматически. А насчет бесконечности -- это да, WINAPI большой...

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

Posted: Sun 26 Oct, 2014 22:49
by Maximus5
Что-то я сомневаюсь, что вы когда-нибудь реально на lua будете использовать LPOVERLAPPED )
IMHO его достаточно на "void*" заменить

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

Posted: Sun 26 Oct, 2014 22:58
by fml2
Реально я его и не собираюсь использовать. Но в объявлении функции (скопировано из MSDN) оно присутствует. Редактировать там что-либо не хочется. Так что в тексте это имя встречается.

Это "реальное" использование? Вроде нет. Но ведь и не воображаемое! :-)

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

Posted: Sun 26 Oct, 2014 23:03
by fml2
Как с помощью string.format вывести значение WINAPI HANDLE? Спецификатора %p в Lua вроде нету. При использовании %u в качестве формата и ffi.cast("unsigned int", handle) в качестве значения выдается ошибка: bad argument #2 to 'format' (number expected, got cdata).

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

Posted: Mon 27 Oct, 2014 00:06
by Shmuel
fml2 wrote:Как с помощью string.format вывести значение WINAPI HANDLE? Спецификатора %p в Lua вроде нету.
В Lua нету, в LuaJIT есть.

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

Posted: Mon 27 Oct, 2014 07:12
by fml2
Я пробовал и с %p, но выводилось просто "%p", т.е. спецификатор ничего не преобразовывал, а выводился просто как строка. Что там используется (просто Lua или LuaJit), в чем между ними разница и как сказать, чем именно хочешь пользоваться, я не знаю.

По идее, любой Jit должен "влезать" сам по мере надобности/целесообразности. И не должен менять результат выполнения программы. Поэтому меня удивляет, что в одном месте %p есть, а в другом нет.

А как сделать без %p?