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

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

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

Post by John Doe » Tue 21 May, 2013 20:20

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

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

Предупреждение: viewtopic.php?p=147610#p147610

User avatar
John Doe
Бюрократ
Posts: 12519
Joined: Wed 27 Apr, 2005 20:42
Has thanked: 33 times
Been thanked: 228 times

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

Post by John Doe » Sat 08 Mar, 2014 11:16

Latest post of the previous page:

Смотрю farapi.lua, и вижу что в определениях констант вместо специфических типов Far API используются стандартные.

Code: Select all

static const /*COLORDIALOGFLAGS*/ uint32_t
    CDF_NONE = 0;
Для чего это сделано?

Shmuel
Posts: 5908
Joined: Thu 23 Mar, 2006 21:36
Location: Israel
Has thanked: 23 times
Been thanked: 228 times

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

Post by Shmuel » Sat 08 Mar, 2014 16:16

http://luajit.org/ext_ffi_semantics.html
static const declarations only work for integer types up to 32 bits.

User avatar
John Doe
Бюрократ
Posts: 12519
Joined: Wed 27 Apr, 2005 20:42
Has thanked: 33 times
Been thanked: 228 times

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

Post by John Doe » Sat 08 Mar, 2014 16:26

Это ограничение luajit FFI?
Вообще странно, я объявляю static const ULONG SEE_MASK_NO_CONSOLE = 0x00008000; и всё работает без ошибок.
Возможно всё в порядке, если константа фактически умещается в 32 бита.

Не туда смотрю, ULONG как раз 32 бита

User avatar
John Doe
Бюрократ
Posts: 12519
Joined: Wed 27 Apr, 2005 20:42
Has thanked: 33 times
Been thanked: 228 times

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

Post by John Doe » Sat 08 Mar, 2014 16:34

И судя по другим библиотекам что мне попадались - никто особо не заботится о типе констант, а точнее чаще всего в качестве констант используются обычные числовые lua-переменные.

И в связи с этим у меня возник вопрос как правильно обращаться с константами-флагами?
Что происходит когда я передаю C-константы в функции bit.*? bit64.*?
Не происходит ли при этом лишних конвертаций из типов С в lua и обратно?

И нет ли таких конвертаций при обычном суммировании C-констант?

Shmuel
Posts: 5908
Joined: Thu 23 Mar, 2006 21:36
Location: Israel
Has thanked: 23 times
Been thanked: 228 times

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

Post by Shmuel » Sat 08 Mar, 2014 16:59

John Doe wrote:Что происходит когда я передаю C-константы в функции bit.*? bit64.*?
Не происходит ли при этом лишних конвертаций из типов С в lua и обратно?

И нет ли таких конвертаций при обычном суммировании C-констант?
1. За bit.* не беспокойтесь, библиотека встроена в LuaJIT, всё компилируется. В LuaJIT 2.1 библиотека bit работает и с 64-битными данными. А функции bit64.* просто выдадут ошибку при подаче им на вход cdata.

2. Нет.

3. Нет.

User avatar
John Doe
Бюрократ
Posts: 12519
Joined: Wed 27 Apr, 2005 20:42
Has thanked: 33 times
Been thanked: 228 times

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

Post by John Doe » Sat 08 Mar, 2014 17:07

Спасибо.

Ещё один вопрос возник по следуещему абзацу документации:
http://luajit.org/ext_ffi_semantics.html#gc wrote:Similar rules apply for Lua strings which are implicitly converted to "const char *": the string object itself must be referenced somewhere or it'll be garbage collected eventually. The pointer will then point to stale data, which may have already been overwritten. Note that string literals are automatically kept alive as long as the function containing it (actually its prototype) is not garbage collected.
Я не понимаю как именно понимать последнее предложение.
Не могли бы вы привести пример такого использования?

Shmuel
Posts: 5908
Joined: Thu 23 Mar, 2006 21:36
Location: Israel
Has thanked: 23 times
Been thanked: 228 times

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

Post by Shmuel » Sat 08 Mar, 2014 18:53

John Doe wrote:Я не понимаю как именно понимать последнее предложение.
Понимать так: использование стринговых литералов (то-есть: "foo", 'bar', [[baz]]) полностью безопасно, за исключением случаев, когда в другую ф-цию передаётся указатель на литерал, а ф-ция, содержащая этот литерал собирается сборщиком мусора.
  1. function f1()
  2.   return ffi.cast("const char*", "foo")
  3. end
  4.  
  5. local ptr = f1()
  6. f1 = nil
  7. -- после этого ф-ция f1 будет собрана сборщиком мусора
  8. -- использование ptr может быть чревато неприятностями

User avatar
John Doe
Бюрократ
Posts: 12519
Joined: Wed 27 Apr, 2005 20:42
Has thanked: 33 times
Been thanked: 228 times

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

Post by John Doe » Sat 08 Mar, 2014 19:06

Правильно ли я понял, что в первом предложении говорится о том, что опасен такой код :
  1. function f1()
  2.   local str = "foo"
  3.   local ptr = ffi.cast("const char*", str)
  4.   str = nil
  5.   f2(ptr)
  6. end
Но если используется не переменная, а литерал, то это нормально, пока "жива" функция f1:
  1. function f1()
  2.   local ptr = ffi.cast("const char*", "foo")
  3.   f2(ptr)
  4.   -- some other code
  5.   return
  6. end
Но что если вызов f2 - завершающая команда f1?
Это ведь получится tail call?
Как поведёт себя сборщик мусора?

Shmuel
Posts: 5908
Joined: Thu 23 Mar, 2006 21:36
Location: Israel
Has thanked: 23 times
Been thanked: 228 times

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

Post by Shmuel » Sat 08 Mar, 2014 19:14

Оба примера абсолютно безопасны (даже не учитывая, что вы дважды определили local str в первой ф-ции, а это получаются две разных переменных).

Tail call, насколько я понимаю, не должен влиять на сборку мусора.

User avatar
John Doe
Бюрократ
Posts: 12519
Joined: Wed 27 Apr, 2005 20:42
Has thanked: 33 times
Been thanked: 228 times

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

Post by John Doe » Sat 08 Mar, 2014 19:21

Shmuel wrote:Оба примера абсолютно безопасны (даже не учитывая, что вы дважды определили local str в первой ф-ции, а это получаются две разных переменных).
Я не намеренно, уже исправил (убрал local)
Как я понимаю, это будет нарушением, поскольку the string object itself must be referenced somewhere or it'll be garbage collected eventually

Shmuel
Posts: 5908
Joined: Thu 23 Mar, 2006 21:36
Location: Israel
Has thanked: 23 times
Been thanked: 228 times

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

Post by Shmuel » Sat 08 Mar, 2014 19:26

John Doe wrote:Как я понимаю, это будет нарушением, поскольку the string object itself must be referenced somewhere or it'll be garbage collected eventually
Сборщик мусора собирает объекты, а не переменные. ffi.cast("const char*", str) вернёт указатель на литерал, а не на переменную. Поскольку литерал собран сборщиком не будет, то ptr может быть использован безопасно.

User avatar
John Doe
Бюрократ
Posts: 12519
Joined: Wed 27 Apr, 2005 20:42
Has thanked: 33 times
Been thanked: 228 times

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

Post by John Doe » Sat 08 Mar, 2014 19:36

Сборщик мусора собирает объекты, а не переменные
Хм.
Я был уверерен что в данном случае объект-строка потеряв референс (str=nil) становится мусором и может быть собрана сборщиком.

Разве не это имеется ввиду в цитате the string object itself must be referenced somewhere or it'll be garbage collected eventually?

Shmuel
Posts: 5908
Joined: Thu 23 Mar, 2006 21:36
Location: Israel
Has thanked: 23 times
Been thanked: 228 times

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

Post by Shmuel » Sat 08 Mar, 2014 20:33

Объект-строка здесь является литералом, а это особый случай. Он живёт, покуда ф-ция, его содержащая, жива. Даже если ссылок на него не осталось.

User avatar
John Doe
Бюрократ
Posts: 12519
Joined: Wed 27 Apr, 2005 20:42
Has thanked: 33 times
Been thanked: 228 times

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

Post by John Doe » Sat 08 Mar, 2014 20:41

Shmuel wrote:Объект-строка здесь является литералом
А в каких случаях lua-строка не является литералом?
local str = "foo" - это литерал
local str = tostring("foo") - это не литерал?
local str = far.LuafarVersion() - и это не литерал?

Shmuel
Posts: 5908
Joined: Thu 23 Mar, 2006 21:36
Location: Israel
Has thanked: 23 times
Been thanked: 228 times

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

Post by Shmuel » Sat 08 Mar, 2014 20:50

Литерал здесь только "foo". Всё остальное - нет.

User avatar
John Doe
Бюрократ
Posts: 12519
Joined: Wed 27 Apr, 2005 20:42
Has thanked: 33 times
Been thanked: 228 times

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

Post by John Doe » Sat 08 Mar, 2014 21:14

Теперь я вижу что самый первый ваш ответ был вполне полон.
Спасибо за терпение ;-)

gotar
Posts: 316
Joined: Sun 06 Sep, 2009 12:34
Has thanked: 9 times

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

Post by gotar » Tue 06 May, 2014 10:16

Помогите найти ошибку:
  1. local ffi = require("ffi")
  2. ffi.load("kernel32")
  3. ffi.cdef[[
  4. DWORD  GetFullPathName(
  5.     LPCTSTR lpFileName,
  6.     DWORD nBufferLength,
  7.     LPTSTR lpBuffer,
  8.     LPTSTR *lpFilePart
  9. );
  10. ]]
  11. local buf = ffi.new("char[4096]")
  12. ffi.C.GetFullPathName(".", 4096,buf,0)
  13. far.Show(ffi.string(buf))
Выдает:
12: cannot resolve symbol 'GetFullPathName': The specified
procedure could not be found.♪
Описание http://msdn.microsoft.com/en-us/library ... 85%29.aspx
Last edited by HaRT on Tue 06 May, 2014 11:02, edited 1 time in total.
Reason: [codebox=lua file=untitled.lua]

Post Reply

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