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

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

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

Postby John Doe » Tue 21 May, 2013 20:20

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

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

Shmuel
Posts: 4911
Joined: Thu 23 Mar, 2006 21:36
Location: Israel
Has thanked: 11 times
Been thanked: 118 times

Re: luajit в фаре

Postby Shmuel » Tue 21 May, 2013 20:35

John Doe wrote:
Shmuel wrote:Скрипт в предыдущем посте обновлён (был уж совсем плохой).
Больше обновляться не будет, т.к. это всего лишь "демо".

После MacroLoadAll выдаёт ошибку ...pps\far3\Profile\Macros\modules\ljsqlite3\_ljsqlite3.lua:97: ';' expected near '='
И больше не работает.
Это у меня личное?

Не личное.

Shmuel
Posts: 4911
Joined: Thu 23 Mar, 2006 21:36
Location: Israel
Has thanked: 11 times
Been thanked: 118 times

Re: luajit в фаре

Postby Shmuel » Wed 22 May, 2013 16:32

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: 11029
Joined: Wed 27 Apr, 2005 20:42
Has thanked: 9 times
Been thanked: 61 times

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

Postby John Doe » Thu 23 May, 2013 08:37

А что происходит при ffi.cdef, почему повторный вызов приводит к ошибке?

Shmuel
Posts: 4911
Joined: Thu 23 Mar, 2006 21:36
Location: Israel
Has thanked: 11 times
Been thanked: 118 times

Re: luajit в фаре

Postby Shmuel » Thu 23 May, 2013 09:26

John Doe wrote:А что происходит при ffi.cdef, почему повторный вызов приводит к ошибке?

LuaJIT FFI рассматривает переопределение статических констант и enum'ов как ошибку. На повторное определение функций почему-то не жалуется.

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

В своих библиотеках можно перед вызовом ffi.cdef проверить, определена ли та или иная константа.

User avatar
zg
zero-gravity
Posts: 5187
Joined: Tue 15 Mar, 2005 17:36
Location: riga
Been thanked: 40 times
Contact:

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

Postby zg » Tue 16 Jul, 2013 15:50

а вот такой код как-то упростить можно?
  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*.

Shmuel
Posts: 4911
Joined: Thu 23 Mar, 2006 21:36
Location: Israel
Has thanked: 11 times
Been thanked: 118 times

Re: Ликбез по Lua

Postby Shmuel » Tue 16 Jul, 2013 16:06

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 лишь эпизодически).

User avatar
zg
zero-gravity
Posts: 5187
Joined: Tue 15 Mar, 2005 17:36
Location: riga
Been thanked: 40 times
Contact:

Re: Ликбез по Lua

Postby zg » Tue 16 Jul, 2013 16:16

new обнуляет выделенную память, поэтому конечный ноль в моём коде не нужен. про cast читал, но не очевидно что так можно.
а wchar_t* -> string как-нибудь по простому можно?
или так — нормально:
  1. win.Utf16ToUtf8(ffi.string(str,2*kernel32.lstrlenW(str)))

Shmuel
Posts: 4911
Joined: Thu 23 Mar, 2006 21:36
Location: Israel
Has thanked: 11 times
Been thanked: 118 times

Re: Ликбез по Lua

Postby Shmuel » Tue 16 Jul, 2013 16:27

zg wrote:про cast читал, но не очевидно что так можно.

Вот код, откуда это взято, он работает.

а wchar_t* -> string как-нибудь по простому можно?

Например:
  1. local str = win.Utf16ToUtf8(ffi.string(ptr,len))


А kernel32 вроде незачем, скорее всего эта библиотека входит в число тех, которые не надо явно загружать.

User avatar
zg
zero-gravity
Posts: 5187
Joined: Tue 15 Mar, 2005 17:36
Location: riga
Been thanked: 40 times
Contact:

Re: Ликбез по Lua

Postby zg » Tue 16 Jul, 2013 19:10

так у меня работает всегда:
  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

Shmuel
Posts: 4911
Joined: Thu 23 Mar, 2006 21:36
Location: Israel
Has thanked: 11 times
Been thanked: 118 times

Re: Ликбез по Lua

Postby Shmuel » Tue 16 Jul, 2013 19:22

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: )

User avatar
zg
zero-gravity
Posts: 5187
Joined: Tue 15 Mar, 2005 17:36
Location: riga
Been thanked: 40 times
Contact:

Re: Ликбез по Lua

Postby zg » Tue 16 Jul, 2013 19:52

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
результат тот же.

Shmuel
Posts: 4911
Joined: Thu 23 Mar, 2006 21:36
Location: Israel
Has thanked: 11 times
Been thanked: 118 times

Re: Ликбез по Lua

Postby Shmuel » Tue 16 Jul, 2013 20:52

zg wrote:ну изначально у меня так было:
  1. local text=win.Utf8ToUtf16(line:sub(sbegin,send))
  2. if not mydll.myfunc(ffi.cast("const wchar_t*",text)) then
результат тот же.

Приведи пример, который можно повторить, иначе это - голословное утверждение.
А возможно, что просто не хватает "завершающего" нуля.

User avatar
zg
zero-gravity
Posts: 5187
Joined: Tue 15 Mar, 2005 17:36
Location: riga
Been thanked: 40 times
Contact:

Re: Ликбез по Lua

Postby zg » Tue 16 Jul, 2013 21:16

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

Shmuel
Posts: 4911
Joined: Thu 23 Mar, 2006 21:36
Location: Israel
Has thanked: 11 times
Been thanked: 118 times

Re: Ликбез по Lua

Postby Shmuel » Tue 16 Jul, 2013 21:20

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

User avatar
zg
zero-gravity
Posts: 5187
Joined: Tue 15 Mar, 2005 17:36
Location: riga
Been thanked: 40 times
Contact:

Re: luajit в фаре

Postby zg » Thu 08 Aug, 2013 02:56

Shmuel wrote:В своих библиотеках можно перед вызовом ffi.cdef проверить, определена ли та или иная константа.
а как?


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

Who is online

Users browsing this forum: No registered users and 2 guests