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

Столкнулись с проблемой в использовании макросов? Здесь можно получить помощь.
Post Reply
User avatar
John Doe
Бюрократ
Posts: 13801
Joined: Wed 27 Apr, 2005 20:42
Has thanked: 72 times
Been thanked: 425 times
Contact:

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

Post by John Doe »

FFI — одна из стандартных библиотек luajit.
Позволяет из Lua кода вызывать внешние C-функции и использовать структуры данных C.
В данной теме задаём вопросы по использованию FFI

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

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

Предупреждение: viewtopic.php?p=147610#p147610
Shmuel
Posts: 6815
Joined: Thu 23 Mar, 2006 21:36
Location: Israel
Has thanked: 41 times
Been thanked: 526 times

Re: luajit в фаре

Post by Shmuel »

John Doe wrote:
Shmuel wrote:Скрипт в предыдущем посте обновлён (был уж совсем плохой).
Больше обновляться не будет, т.к. это всего лишь "демо".
После MacroLoadAll выдаёт ошибку ...pps\far3\Profile\Macros\modules\ljsqlite3\_ljsqlite3.lua:97: ';' expected near '='
И больше не работает.
Это у меня личное?
Не личное.
Shmuel
Posts: 6815
Joined: Thu 23 Mar, 2006 21:36
Location: Israel
Has thanked: 41 times
Been thanked: 526 times

Re: luajit в фаре

Post 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
User avatar
John Doe
Бюрократ
Posts: 13801
Joined: Wed 27 Apr, 2005 20:42
Has thanked: 72 times
Been thanked: 425 times
Contact:

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

Post by John Doe »

А что происходит при ffi.cdef, почему повторный вызов приводит к ошибке?
Shmuel
Posts: 6815
Joined: Thu 23 Mar, 2006 21:36
Location: Israel
Has thanked: 41 times
Been thanked: 526 times

Re: luajit в фаре

Post by Shmuel »

John Doe wrote:А что происходит при ffi.cdef, почему повторный вызов приводит к ошибке?
LuaJIT FFI рассматривает переопределение статических констант и enum'ов как ошибку. На повторное определение функций почему-то не жалуется.

Почему сообщение было такое невнятное, не анализировал.

В своих библиотеках можно перед вызовом ffi.cdef проверить, определена ли та или иная константа.
User avatar
zg
zero-gravity
Posts: 6015
Joined: Tue 15 Mar, 2005 17:36
Location: riga
Been thanked: 185 times
Contact:

Использование FFI

Post by zg »

а вот такой код как-то упростить можно?
  1. local word_utf16=win.Utf8ToUtf16(word)
  2.  
  3. local word_cdata=ffi.new("wchar_t[?]",string.len(word_utf16)/2+1)
  4.  
  5. ffi.copy(word_cdata,word_utf16)
  6.  
  7. word_cdata[string.len(word_utf16)/2]=0
задача строку в utf8 преобразовать в wchar_t*.
Shmuel
Posts: 6815
Joined: Thu 23 Mar, 2006 21:36
Location: Israel
Has thanked: 41 times
Been thanked: 526 times

Re: Ликбез по Lua

Post by Shmuel »

zg wrote:а вот такой код как-то упростить можно?
Нашёл у себя такие (не связанные друг с другом) куски кода:
  1. local function Utf16Buf (str)
  2.  
  3.   str = win.Utf8ToUtf16(str)
  4.  
  5.   local buf = ffi.new("wchar_t[?]", #str/2+1)
  6.  
  7.   ffi.copy(buf, str, #str)
  8.  
  9.   return buf
  10.  
  11. end
  1. local text = win.Utf8ToUtf16(str)
  2.  
  3. item.Text = ffi.cast("const wchar_t*", text)
(Но я пока пользуюсь FFI лишь эпизодически).
User avatar
zg
zero-gravity
Posts: 6015
Joined: Tue 15 Mar, 2005 17:36
Location: riga
Been thanked: 185 times
Contact:

Re: Ликбез по Lua

Post by zg »

new обнуляет выделенную память, поэтому конечный ноль в моём коде не нужен. про cast читал, но не очевидно что так можно.
а wchar_t* -> string как-нибудь по простому можно?
или так — нормально:
  1. win.Utf16ToUtf8(ffi.string(str,2*kernel32.lstrlenW(str)))
Shmuel
Posts: 6815
Joined: Thu 23 Mar, 2006 21:36
Location: Israel
Has thanked: 41 times
Been thanked: 526 times

Re: Ликбез по Lua

Post by Shmuel »

zg wrote:про cast читал, но не очевидно что так можно.
Вот код, откуда это взято, он работает.
а wchar_t* -> string как-нибудь по простому можно?
Например:
  1. local str = win.Utf16ToUtf8(ffi.string(ptr,len))
А kernel32 вроде незачем, скорее всего эта библиотека входит в число тех, которые не надо явно загружать.
User avatar
zg
zero-gravity
Posts: 6015
Joined: Tue 15 Mar, 2005 17:36
Location: riga
Been thanked: 185 times
Contact:

Re: Ликбез по Lua

Post by zg »

так у меня работает всегда:
  1. local function ToWChar(str)
  2.  
  3.   str=win.Utf8ToUtf16(str)
  4.  
  5.   local result=ffi.new("wchar_t[?]",#str/2+1)
  6.  
  7.   ffi.copy(result,str)
  8.  
  9.   return result
  10.  
  11. end
так тот же самый код — рандомно:
  1. local function ToWChar(str)
  2.  
  3.   local text = win.Utf8ToUtf16(str)
  4.  
  5.   local result = ffi.cast("const wchar_t*", text)
  6.  
  7.   return result
  8.  
  9. end
Shmuel
Posts: 6815
Joined: Thu 23 Mar, 2006 21:36
Location: Israel
Has thanked: 41 times
Been thanked: 526 times

Re: Ликбез по Lua

Post by Shmuel »

zg wrote:так тот же самый код — рандомно:
  1. local function ToWChar(str)
  2.  
  3.   local text = win.Utf8ToUtf16(str)
  4.  
  5.   local result = ffi.cast("const wchar_t*", text)
  6.  
  7.   return result
  8.  
  9. end
Это неудивительно, т.к. переменная text становится мусором при выходе из функции и, следовательно, может быть собрана сборщиком мусора. (Но я так делать ни разу не советовал. :ha: )
User avatar
zg
zero-gravity
Posts: 6015
Joined: Tue 15 Mar, 2005 17:36
Location: riga
Been thanked: 185 times
Contact:

Re: Ликбез по Lua

Post by zg »

Shmuel wrote:Это неудивительно, т.к. переменная text становится мусором при выходе из функции и, следовательно, может быть собрана сборщиком мусора. (Но я так делать ни разу не советовал. :ha: )
ну изначально у меня так было:
  1. local text=win.Utf8ToUtf16(line:sub(sbegin,send))
  2.  
  3. if not mydll.myfunc(ffi.cast("const wchar_t*",text)) then
результат тот же.
Shmuel
Posts: 6815
Joined: Thu 23 Mar, 2006 21:36
Location: Israel
Has thanked: 41 times
Been thanked: 526 times

Re: Ликбез по Lua

Post by Shmuel »

zg wrote:ну изначально у меня так было:
  1. local text=win.Utf8ToUtf16(line:sub(sbegin,send))
  2.  
  3. if not mydll.myfunc(ffi.cast("const wchar_t*",text)) then
результат тот же.
Приведи пример, который можно повторить, иначе это - голословное утверждение.
А возможно, что просто не хватает "завершающего" нуля.
User avatar
zg
zero-gravity
Posts: 6015
Joined: Tue 15 Mar, 2005 17:36
Location: riga
Been thanked: 185 times
Contact:

Re: Ликбез по Lua

Post by zg »

Shmuel wrote:Приведи пример, который можно повторить, иначе это - голословное утверждение.
ну отчего ж сразу голословное?
А возможно, что просто не хватает "завершающего" нуля.
а вот так, да, работает:
  1. local text=win.Utf8ToUtf16(line:sub(sbegin,send).."\0")
  2.  
  3. if not mydll.myfunc(ffi.cast("const wchar_t*",text)) then
Shmuel
Posts: 6815
Joined: Thu 23 Mar, 2006 21:36
Location: Israel
Has thanked: 41 times
Been thanked: 526 times

Re: Ликбез по Lua

Post by Shmuel »

Я в своё время просил Роберто (в форуме Lua, можно найти) добавлять два нуля к стрингам вместо одного, но он не пошёл на это.
Post Reply

Return to “Нужна помощь”