Вопросы по использованию FFI
- John Doe
- Бюрократ
- Posts: 13807
- Joined: Wed 27 Apr, 2005 20:42
- Has thanked: 73 times
- Been thanked: 426 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: 145
- Joined: Thu 04 Oct, 2012 13:53
- Location: Hamburg, DE
- Has thanked: 2 times
- Been thanked: 2 times
ffi.C и unicode/multibyte ... string
Latest post of the previous page:
Пардон, я наверху что-то напутал походу с ffi.cdef, оно же второй раз не переопределяется и об ошибке не сообщает, нужно было Фар перегружать.На самом деле у меня работающий пример выглядит так: Я конечно понимаю, что так делать не совсем чисто, но для машины-то без разницы, будь то char* byte* или short*.
- HaRT
- Moderator
- Posts: 10822
- Joined: Tue 30 Aug, 2005 17:21
- Has thanked: 221 times
- Been thanked: 358 times
Re: ffi.C и unicode/multibyte ... string
Машина машине рознь. На многих RISC-архитектурах у char* и short* почти наверняка будет разное выравнивание, что чревато в лучшем случае просадкой производительности, а в типичном — “unaligned” exception. И да, некоторые из таких машин работают (работали?) под управлением тех или иных Windows.EGez wrote:Я конечно понимаю, что так делать не совсем чисто, но для машины-то без разницы, будь то char* byte* или short*.
Фар есть инструмент, а не нянька. © 2009 DrKnS
-
- Posts: 145
- Joined: Thu 04 Oct, 2012 13:53
- Location: Hamburg, DE
- Has thanked: 2 times
- Been thanked: 2 times
Re: ffi.C и unicode/multibyte ... string
Ну, совсем экзотикой можно принебречь...HaRT wrote:Машина машине рознь. На многих RISC-архитектурах у char* и short* почти наверняка будет разное выравнивание, что чревато в лучшем случае просадкой производительности, а в типичном — “unaligned” exception. И да, некоторые из таких машин работают (работали?) под управлением тех или иных Windows.
- John Doe
- Бюрократ
- Posts: 13807
- Joined: Wed 27 Apr, 2005 20:42
- Has thanked: 73 times
- Been thanked: 426 times
- Contact:
Re: Вопросы по использованию FFI
Хотел составить функцию для превращения строки Lua в указатель, для передачи входных параметров в разные WinAPI-функции.
Сделал, работает:Но перечитав тему засомневался, ведь результат win.Utf8ToUtf16 при выходе из функции становится мусором?
С другой стороны, полученный указатель и не требуется долго хранить...
В общем, на первой странице похожий пример рассматривался, решили что нельзя.
Если только не сохранить результат win.Utf8ToUtf16 в актуальную переменную. Или использовать ffi.new/ffi.copy
Хотя тогда я несовсем понимаю, почему в другом примере на первой странице делается так:Разве тут есть гарантия, что данные доживут до момента их использования?
И последний момент: всегда ли корректно кастить в "void*", не разделяя что там на самом деле требуется принимающим функциям
(const wchar_t* / wchar_t* / char* / и т.д.) ?
Сделал, работает:
Code: Select all
local function str2p(str)
return ffi.cast("void*",win.Utf8ToUtf16(str .. '\0'))
end
С другой стороны, полученный указатель и не требуется долго хранить...
В общем, на первой странице похожий пример рассматривался, решили что нельзя.
Если только не сохранить результат win.Utf8ToUtf16 в актуальную переменную. Или использовать ffi.new/ffi.copy
Хотя тогда я несовсем понимаю, почему в другом примере на первой странице делается так:
Code: Select all
local PluginId = ffi.cast("const GUID*", win.Uuid("4EBBEFC8-2084-4B7F-94C0-692CE136894D"))
local MenuId = ffi.cast("const GUID*", win.Uuid("6C47D27E-3E7E-4C65-916D-E1B1A31527AD"))
--пропущено 10 строк кода
psi.Menu(PluginId,MenuId,-1,-1,0,0,nil,nil,nil,nil,nil,items,N)
И последний момент: всегда ли корректно кастить в "void*", не разделяя что там на самом деле требуется принимающим функциям
(const wchar_t* / wchar_t* / char* / и т.д.) ?
-
- Posts: 6819
- Joined: Thu 23 Mar, 2006 21:36
- Location: Israel
- Has thanked: 41 times
- Been thanked: 528 times
Re: Вопросы по использованию FFI
ffi.cast от "незакреплённой" величины - это скорее всего баг. То, что он не всегда проявляется, тоже понятно. Чтобы стимулировать проявление бага, можно вызвать пару раз collectgarbage("collect") между получением и использованием.
Пример с гуидом - да, видимо баг.
ffi.cast("void*", value) для передачи функциям Windows API / Far API корректен, если value указывает на то, что функция ожидает получить.
Пример с гуидом - да, видимо баг.
ffi.cast("void*", value) для передачи функциям Windows API / Far API корректен, если value указывает на то, что функция ожидает получить.
- John Doe
- Бюрократ
- Posts: 13807
- Joined: Wed 27 Apr, 2005 20:42
- Has thanked: 73 times
- Been thanked: 426 times
- Contact:
Re: Вопросы по использованию FFI
Спасибо.
А этот код можно ли заменить на ?
Есть тут какие-то грабли?
И правильно ли я понимаю что
Т.е. по большому счёту тип не важен, главное выделять
А этот код можно ли заменить на ?
Есть тут какие-то грабли?
И правильно ли я понимаю что
ffi.new("wchar_t[?]",BufferLength/2)
это то же самое что ffi.new("char[?]",BufferLength)
Т.е. по большому счёту тип не важен, главное выделять
BufferLength/ffi.sizeof(type)
?- HaRT
- Moderator
- Posts: 10822
- Joined: Tue 30 Aug, 2005 17:21
- Has thanked: 221 times
- Been thanked: 358 times
Re: Вопросы по использованию FFI
Не знаю, как там в Lua/FFI, а в Си/Си++ это будет корректно только на конкретных платформах. На других же платформах значение Пи может достигать четырёх размерJohn Doe wrote:правильно ли я понимаю чтоffi.new("wchar_t[?]",BufferLength/2)
это то же самое чтоffi.new("char[?]",BufferLength)
[...]?
sizeof(wchar_t)
может заметно отличаться.Фар есть инструмент, а не нянька. © 2009 DrKnS
- John Doe
- Бюрократ
- Posts: 13807
- Joined: Wed 27 Apr, 2005 20:42
- Has thanked: 73 times
- Been thanked: 426 times
- Contact:
Re: Вопросы по использованию FFI
HaRT
Потому я и указал что в общем случае зависит от sizeof.
Но на тех платформах, на которых вообще возможен запуск фара, этим можно пренебречь.
Во всяком случае такой вывод я делаю из примеров кода специалистов:
Потому я и указал что в общем случае зависит от sizeof.
Но на тех платформах, на которых вообще возможен запуск фара, этим можно пренебречь.
Во всяком случае такой вывод я делаю из примеров кода специалистов:
spell.lua wrote:Code: Select all
local function ToWChar(str) str=win.Utf8ToUtf16(str) local result=ffi.new("wchar_t[?]",#str/2+1) ffi.copy(result,str) return result end
-
- Posts: 6819
- Joined: Thu 23 Mar, 2006 21:36
- Location: Israel
- Has thanked: 41 times
- Been thanked: 528 times
Re: Вопросы по использованию FFI
1. Граблей не вижу, но не забывать о дополнительном нулевом символе в конце.John Doe wrote:А этот код можно ли заменить на ?
Есть тут какие-то грабли?
И правильно ли я понимаю чтоffi.new("wchar_t[?]",BufferLength/2)
это то же самое чтоffi.new("char[?]",BufferLength)
Т.е. по большому счёту тип не важен, главное выделятьBufferLength/ffi.sizeof(type)
?
2. Правильно, при условии, что ф-ция API получит на вход тот тип указателя, с которым она объявлена (или void*).
- zg
- zero-gravity
- Posts: 6016
- Joined: Tue 15 Mar, 2005 17:36
- Location: riga
- Been thanked: 185 times
- Contact:
Re: Вопросы по использованию FFI
потенциально есть грабли с выравниванием.John Doe wrote:Есть тут какие-то грабли?
- John Doe
- Бюрократ
- Posts: 13807
- Joined: Wed 27 Apr, 2005 20:42
- Has thanked: 73 times
- Been thanked: 426 times
- Contact:
Re: Вопросы по использованию FFI
zg
Т.е. адрес, по которому находится lua-строка, может прийтись не на начало машинного слова?
Выходит не стоит так делать.
Ещё вопрос.
В буфере из примера выше находится C-строка неизвестной длины.
Как лучше всего перевести её в lua-строку?
Очевидно надо использовать ffi.string, но поскольку длина заранее неизвестна, то возможны варианты
- объявить и использовать
- перевести в строку весь буфер, и использовать
Почему-то кажется что должен быть более изящный способ.
Т.е. адрес, по которому находится lua-строка, может прийтись не на начало машинного слова?
Выходит не стоит так делать.
Ещё вопрос.
В буфере из примера выше находится C-строка неизвестной длины.
Как лучше всего перевести её в lua-строку?
Очевидно надо использовать ffi.string, но поскольку длина заранее неизвестна, то возможны варианты
- объявить и использовать
C.lstrlenW
- перевести в строку весь буфер, и использовать
match"(.-)%z"
Почему-то кажется что должен быть более изящный способ.
- zg
- zero-gravity
- Posts: 6016
- Joined: Tue 15 Mar, 2005 17:36
- Location: riga
- Been thanked: 185 times
- Contact:
Re: Вопросы по использованию FFI
в теории, да. на практике, наверное, нет. но кто ж его знает, что случится завтра.John Doe wrote:Т.е. адрес, по которому находится lua-строка, может прийтись не на начало машинного слова?
я так делал в спелере, вроде даже что-то обсуждали тогда, и типа нет вариантов проще.John Doe wrote:- объявить и использоватьC.lstrlenW
Почему-то кажется что должен быть более изящный способ.
- John Doe
- Бюрократ
- Posts: 13807
- Joined: Wed 27 Apr, 2005 20:42
- Has thanked: 73 times
- Been thanked: 426 times
- Contact:
Re: Вопросы по использованию FFI
Значит и пример с первой страницы не полностью надёжен?zg wrote:в теории, да. на практике, наверное, нет. но кто ж его знает, что случится завтра.John Doe wrote:Т.е. адрес, по которому находится lua-строка, может прийтись не на начало машинного слова?
Нашёл в picture.lua:204 такой код:Shmuel wrote:ffi.cast от "незакреплённой" величины - это скорее всего баг.
Code: Select all
local delayraw=ffi.cast("PropertyItem*",ffi.new("char[?]",delaysize[0]))
- zg
- zero-gravity
- Posts: 6016
- Joined: Tue 15 Mar, 2005 17:36
- Location: riga
- Been thanked: 185 times
- Contact:
Re: Вопросы по использованию FFI
вопрос в том, как работает аллокатор строк и ffi.new. возможно там такое выравнивание, что хватит всем.John Doe wrote:Значит и пример с первой страницы не полностью надёжен?
спасибо, поправил.John Doe wrote:Нашёл в picture.lua:204 такой код:
update:
тут пишут, что «8 byte alignment is guaranteed» для ffi.new.
-
- Posts: 6819
- Joined: Thu 23 Mar, 2006 21:36
- Location: Israel
- Has thanked: 41 times
- Been thanked: 528 times
Re: Вопросы по использованию FFI
Да, для этого даже добавлен файл LuaMacro\farapi.lua.John Doe wrote:Возможно ли через ffi как-то воспользоваться C-функциями far api?
Для получения указателя на PluginStartupInfo есть ф-ция far.CPluginStartupInfo, нужно cделать ffi.cast() от результата её вызова.