Page 1 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: luajit в фаре
Posted: Tue 21 May, 2013 20:35
by Shmuel
John Doe wrote: Shmuel wrote:Скрипт в предыдущем посте обновлён (был уж совсем плохой).
Больше обновляться не будет, т.к. это всего лишь "демо".
После MacroLoadAll выдаёт ошибку
...pps\far3\Profile\Macros\modules\ljsqlite3\_ljsqlite3.lua:97: ';' expected near '='
И больше не работает.
Это у меня личное?
Не личное.
Re: luajit в фаре
Posted: Wed 22 May, 2013 16:32
by Shmuel
John Doe wrote: После MacroLoadAll выдаёт ошибку ...pps\far3\Profile\Macros\modules\ljsqlite3\_ljsqlite3.lua:97: ';' expected near '='
Начиная со следующей ночной сборки, подобные проблемы будут лечиться таким образом (подробнее - в macroapi_manual):
Вопросы по использованию FFI
Posted: Thu 23 May, 2013 08:37
by John Doe
А что происходит при ffi.cdef, почему повторный вызов приводит к ошибке?
Re: luajit в фаре
Posted: Thu 23 May, 2013 09:26
by Shmuel
John Doe wrote: А что происходит при ffi.cdef, почему повторный вызов приводит к ошибке?
LuaJIT FFI рассматривает переопределение статических констант и enum'ов как ошибку. На повторное определение функций почему-то не жалуется.
Почему сообщение было такое невнятное, не анализировал.
В
своих библиотеках можно перед вызовом ffi.cdef проверить, определена ли та или иная константа.
Использование FFI
Posted: Tue 16 Jul, 2013 15:50
by zg
а вот такой код как-то упростить можно?
local word_utf16= win. Utf8ToUtf16( word)
local word_cdata= ffi. new( "wchar_t[?]" , string.len ( word_utf16) / 2 + 1 )
ffi. copy( word_cdata, word_utf16)
word_cdata[ string.len ( word_utf16) / 2 ] = 0
задача строку в utf8 преобразовать в wchar_t*.
Re: Ликбез по Lua
Posted: Tue 16 Jul, 2013 16:06
by Shmuel
zg wrote: а вот такой код как-то упростить можно?
Нашёл у себя такие (не связанные друг с другом) куски кода:
local function Utf16Buf ( str)
str = win. Utf8ToUtf16( str)
local buf = ffi. new( "wchar_t[?]" , # str/ 2 + 1 )
ffi. copy( buf, str, # str)
return buf
end
local text = win. Utf8ToUtf16( str)
item. Text = ffi. cast( "const wchar_t*" , text)
(Но я пока пользуюсь FFI лишь эпизодически).
Re: Ликбез по Lua
Posted: Tue 16 Jul, 2013 16:16
by zg
new обнуляет выделенную память, поэтому конечный ноль в моём коде не нужен. про cast читал, но не очевидно что так можно.
а wchar_t* -> string как-нибудь по простому можно?
или так — нормально:
win. Utf16ToUtf8( ffi. string ( str, 2 * kernel32. lstrlenW( str) ) )
Re: Ликбез по Lua
Posted: Tue 16 Jul, 2013 16:27
by Shmuel
zg wrote: про cast читал, но не очевидно что так можно.
Вот код, откуда это взято, он работает.
local ffi = require "ffi"
require 'far2.ffi.farapi'
local N= 10000
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" ) )
local item = ffi. new( "struct FarMenuItem" )
local items = ffi. new( "struct FarMenuItem[?]" , N)
local text = win. Utf8ToUtf16( ( "baba" ) : rep( 250 ) )
item. Text = ffi. cast( "const wchar_t*" , text)
for k= 0 , N- 1 do
ffi. copy( items[ k] , item, ffi. sizeof( item) )
end
local psi = ffi. new( "struct PluginStartupInfo*" , far. CPluginStartupInfo( ) )
psi. Menu( PluginId, MenuId,- 1 ,- 1 , 0 , 0 , nil , nil , nil , nil , nil , items, N)
а wchar_t* -> string как-нибудь по простому можно?
Например:
local str = win. Utf16ToUtf8( ffi. string ( ptr, len) )
А kernel32 вроде незачем, скорее всего эта библиотека входит в число тех, которые не надо явно загружать.
Re: Ликбез по Lua
Posted: Tue 16 Jul, 2013 19:10
by zg
так у меня работает всегда:
local function ToWChar( str)
str= win. Utf8ToUtf16( str)
local result= ffi. new( "wchar_t[?]" ,# str/ 2 + 1 )
ffi. copy( result, str)
return result
end
так тот же самый код — рандомно:
local function ToWChar( str)
local text = win. Utf8ToUtf16( str)
local result = ffi. cast( "const wchar_t*" , text)
return result
end
Re: Ликбез по Lua
Posted: Tue 16 Jul, 2013 19:22
by Shmuel
zg wrote: так тот же самый код — рандомно:
local function ToWChar( str)
local text = win. Utf8ToUtf16( str)
local result = ffi. cast( "const wchar_t*" , text)
return result
end
Это неудивительно, т.к. переменная
text становится мусором при выходе из функции и, следовательно, может быть собрана сборщиком мусора. (Но я
так делать ни разу не советовал.
)
Re: Ликбез по Lua
Posted: Tue 16 Jul, 2013 19:52
by zg
Shmuel wrote: Это неудивительно, т.к. переменная
text становится мусором при выходе из функции и, следовательно, может быть собрана сборщиком мусора. (Но я
так делать ни разу не советовал.
)
ну изначально у меня так было:
local text= win. Utf8ToUtf16( line: sub( sbegin, send) )
if not mydll. myfunc( ffi. cast( "const wchar_t*" , text) ) then
результат тот же.
Re: Ликбез по Lua
Posted: Tue 16 Jul, 2013 20:52
by Shmuel
zg wrote: ну изначально у меня так было:
local text= win. Utf8ToUtf16( line: sub( sbegin, send) )
if not mydll. myfunc( ffi. cast( "const wchar_t*" , text) ) then
результат тот же.
Приведи пример, который можно повторить, иначе это - голословное утверждение.
А возможно, что просто не хватает "завершающего" нуля.
Re: Ликбез по Lua
Posted: Tue 16 Jul, 2013 21:16
by zg
Shmuel wrote: Приведи пример, который можно повторить, иначе это - голословное утверждение.
ну отчего ж сразу голословное?
А возможно, что просто не хватает "завершающего" нуля.
а вот так, да, работает:
local text= win. Utf8ToUtf16( line: sub( sbegin, send) .. "\0 " )
if not mydll. myfunc( ffi. cast( "const wchar_t*" , text) ) then
Re: Ликбез по Lua
Posted: Tue 16 Jul, 2013 21:20
by Shmuel
Я в своё время просил Роберто (в форуме Lua, можно найти) добавлять два нуля к стрингам вместо одного, но он не пошёл на это.