Page 1 of 14

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

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

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

Предупреждение: 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):

Code: Select all

package.nounload.ljsqlite3 = true

Вопросы по использованию 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
а вот такой код как-то упростить можно?
  1. local word_utf16=win.Utf8ToUtf16(word)
  2. local word_cdata=ffi.new("wchar_t[?]",string.len(word_utf16)/2+1)
  3. ffi.copy(word_cdata,word_utf16)
  4. word_cdata[string.len(word_utf16)/2]=0
задача строку в utf8 преобразовать в wchar_t*.

Re: Ликбез по Lua

Posted: Tue 16 Jul, 2013 16:06
by Shmuel
zg wrote:а вот такой код как-то упростить можно?
Нашёл у себя такие (не связанные друг с другом) куски кода:
  1. local function Utf16Buf (str)
  2.   str = win.Utf8ToUtf16(str)
  3.   local buf = ffi.new("wchar_t[?]", #str/2+1)
  4.   ffi.copy(buf, str, #str)
  5.   return buf
  6. end
  1. local text = win.Utf8ToUtf16(str)
  2. 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 как-нибудь по простому можно?
или так — нормально:
  1. win.Utf16ToUtf8(ffi.string(str,2*kernel32.lstrlenW(str)))

Re: Ликбез по Lua

Posted: Tue 16 Jul, 2013 16:27
by Shmuel
zg wrote:про cast читал, но не очевидно что так можно.
Вот код, откуда это взято, он работает.
а wchar_t* -> string как-нибудь по простому можно?
Например:
  1. local str = win.Utf16ToUtf8(ffi.string(ptr,len))
А kernel32 вроде незачем, скорее всего эта библиотека входит в число тех, которые не надо явно загружать.

Re: Ликбез по Lua

Posted: Tue 16 Jul, 2013 19:10
by zg
так у меня работает всегда:
  1. local function ToWChar(str)
  2.   str=win.Utf8ToUtf16(str)
  3.   local result=ffi.new("wchar_t[?]",#str/2+1)
  4.   ffi.copy(result,str)
  5.   return result
  6. end
так тот же самый код — рандомно:
  1. local function ToWChar(str)
  2.   local text = win.Utf8ToUtf16(str)
  3.   local result = ffi.cast("const wchar_t*", text)
  4.   return result
  5. end

Re: Ликбез по Lua

Posted: Tue 16 Jul, 2013 19:22
by Shmuel
zg wrote:так тот же самый код — рандомно:
  1. local function ToWChar(str)
  2.   local text = win.Utf8ToUtf16(str)
  3.   local result = ffi.cast("const wchar_t*", text)
  4.   return result
  5. end
Это неудивительно, т.к. переменная text становится мусором при выходе из функции и, следовательно, может быть собрана сборщиком мусора. (Но я так делать ни разу не советовал. :ha: )

Re: Ликбез по Lua

Posted: Tue 16 Jul, 2013 19:52
by zg
Shmuel wrote:Это неудивительно, т.к. переменная text становится мусором при выходе из функции и, следовательно, может быть собрана сборщиком мусора. (Но я так делать ни разу не советовал. :ha: )
ну изначально у меня так было:
  1. local text=win.Utf8ToUtf16(line:sub(sbegin,send))
  2. if not mydll.myfunc(ffi.cast("const wchar_t*",text)) then
результат тот же.

Re: Ликбез по Lua

Posted: Tue 16 Jul, 2013 20:52
by Shmuel
zg wrote:ну изначально у меня так было:
  1. local text=win.Utf8ToUtf16(line:sub(sbegin,send))
  2. if not mydll.myfunc(ffi.cast("const wchar_t*",text)) then
результат тот же.
Приведи пример, который можно повторить, иначе это - голословное утверждение.
А возможно, что просто не хватает "завершающего" нуля.

Re: Ликбез по Lua

Posted: Tue 16 Jul, 2013 21:16
by zg
Shmuel wrote:Приведи пример, который можно повторить, иначе это - голословное утверждение.
ну отчего ж сразу голословное?
А возможно, что просто не хватает "завершающего" нуля.
а вот так, да, работает:
  1. local text=win.Utf8ToUtf16(line:sub(sbegin,send).."\0")
  2. if not mydll.myfunc(ffi.cast("const wchar_t*",text)) then

Re: Ликбез по Lua

Posted: Tue 16 Jul, 2013 21:20
by Shmuel
Я в своё время просил Роберто (в форуме Lua, можно найти) добавлять два нуля к стрингам вместо одного, но он не пошёл на это.

Re: luajit в фаре

Posted: Thu 08 Aug, 2013 02:56
by zg
Shmuel wrote:В своих библиотеках можно перед вызовом ffi.cdef проверить, определена ли та или иная константа.
а как?