Size: a a a

2021 July 02

AP

Andrey Privalov in Tarantool
ниже там хабр статьи вылезаю, не страшно)
источник

AS

Andrey Syvrachev in Tarantool
Ребят, вот такой есть вопрос.
Мне надо вернуть CDATA из Си функции. При этом на уровне Си есть буфер, выделенный средствами Си (вне ЛУА).
Я не могу понять как это сделать.
lua_pushlightuserdata
?

Я не понимаю как мне в Луа преобразовать потом указатель в CData
При этом я не хочу копирования, мне достаточно ссылки на память что в Си
источник

MF

Michael Filonenko in Tarantool
ffi?
источник

AS

Andrey Syvrachev in Tarantool
ffi возможно
источник

AS

Andrey Syvrachev in Tarantool
То есть так как у нас фиберы. Я вроде как могу быть уверен, что сразу после вызова Си функции, у меня память на которую она вернула указатель будет еще жива. Я сам управляю ее освобождением.
источник

VV

Vladimir Voznesensky in Tarantool
Вызвать из Луа через ffi освободитель памяти, когда она больше не нужна.
источник

AS

Andrey Syvrachev in Tarantool
Я вот тут нашел что-то, но не хватает рабочего примера
https://luajit.org/ext_ffi_api.html
источник

AS

Andrey Syvrachev in Tarantool
Насколько я понял, LUA дергает сам освободитель памяти, и можно подставить свою реализацию его
источник

MF

Michael Filonenko in Tarantool
Можно глянуть пример работы с ffi в github.com/tarantool/luapg
источник

VG

Vladislav Grubov in Tarantool
ох, мне кажется из чистого СИ лучше не возвращать cdata. Когда-то в Тарантуле так делали, но вроде отказались.
Если вы хотите вызывать Си функцию, а потом в луа разгребать, то нужно что-то типа:

ffi.cdef [[ my_precious_struct_t * my_func(...) ]]
local rv = ffi.C.my_func(...) -- cdata: ctype<my_precious_struct_t>
источник

VG

Vladislav Grubov in Tarantool
да, для этого есть ffi.gc, позволяет указать финализатор, в котором можно очистить память, классический пример:

local my_buffer = ffi.gc(ffi.C.malloc(4096), ffi.C.free)
источник

AS

Andrey Syvrachev in Tarantool
Фактически мне надо подставить массив/буфер, чтобы он возвращался на http/get запрос.

local function get_segment(req)
   
log.info('get_segment %s', req.path)
   return { status = 200,
            headers = {
                ['content-type'] = 'video/mp2t',
            },
            body =
dvr.get_segment(0)
   }
end


server:route({ path = 's/:num', method = 'GET' }, get_segmentget_segment)

dvr.get_segment() -> эта функция имплементирована на Си
- может ли она вовращать CData ?

Или я должен вовзращать из нее указатель на внутренние буфера в Си области, а тут как-то через ffi преобразовывать?
источник

AS

Andrey Syvrachev in Tarantool
Я хотел бы ZeroCopy
источник

AS

Andrey Syvrachev in Tarantool
local my_buffer = ffi.gc(my_pointer_from_C_func, my_C_finalizer)

??? так ?
источник

VG

Vladislav Grubov in Tarantool
будет zerocopy на промежутке C -> Lua. Но перед записью в сокет клиента, придется сериализовать msgpack, вроде бы, там будет копирование
источник

AS

Andrey Syvrachev in Tarantool
да - меня это устроит
источник

AS

Andrey Syvrachev in Tarantool
Возможно имеет смысл подключить http сервер на Си уровне? Будет проще.
может быть tarantool/httpng лучше использовать?
источник

N

Nobody in Tarantool
Lightuserdata просто копируется в луа как указатель, в отличие от просто Userdata, где копируется вся выделенная область памяти
источник

VG

Vladislav Grubov in Tarantool
смотря что за поинтер, если char *, то вроде он его не десериализует, придется делать что-то типа: ffi.string(ffi.gc(dvr.get_segment(0), finalizer)), но ffi.string сделает копирование 🙁
источник

AS

Andrey Syvrachev in Tarantool
static int get_segment(struct lua_State *L)
{
   LUA_INTEGER segment_num = lua_tointeger(L, 1);

say_info("get_segment_%d:[%d,%d]",segment_num);

static unsigned char userData[] = "hello";

lua_pushlightuserdata(L,&userData);
return 1;
}
источник