Почему LuaJIT выдает слишком много ошибок обратных вызовов из этого простого кода?

Я использую LuaJIT и сталкиваюсь с исключением «слишком много обратных вызовов» с этим кодом. Я знаю, что существует ограничение на количество генерируемых обратных вызовов c, но, насколько я знаю, это должно генерировать только один обратный вызов... верно?

ffi = require('ffi')
ffi.cdef([[typedef double cpFloat;
typedef struct cpSpace cpSpace;
typedef struct cpBody cpBody;

cpSpace* cpSpaceNew(void);
cpBody* cpBodyNew(cpFloat mass, cpFloat moment);
cpBody* cpSpaceAddBody(cpSpace *space, cpBody *body);

typedef void (*cpSpaceBodyIteratorFunc)(cpBody *body, void *data);
void cpSpaceEachBody(cpSpace *space, cpSpaceBodyIteratorFunc func, void *data);

]])

chipmunk = ffi.load("chipmunk")
space = chipmunk.cpSpaceNew()
body = chipmunk.cpBodyNew(10, 100)
chipmunk.cpSpaceAddBody(space, body)

drawBody = function(body, x) end
CALL_COUNT = 5000
for i = 1, CALL_COUNT do
  chipmunk.cpSpaceEachBody(space, drawBody, nil)
end

Если CALL_COUNT уменьшить до 500, работает без ошибок.

Исключение следующее:

Error: main.lua:25: too many callbacks
stack traceback:
    [C]: in function 'cpSpaceEachBody'
    mainmoon.lua:25: in main chunk
    [C]: in function 'require'
    main.lua:1: in main chunk
    [C]: in function 'require'
    [string "boot.lua"]:374: in function <[string "boot.lua"]:244>
    [C]: in function 'xpcall'

Контекст: я интегрирую Chipmunk с платформой Love2D в Mac OS X.


person Bob Terrapin    schedule 25.06.2015    source источник


Ответы (1)


В LuaJIT обратные вызовы C являются конечным ресурсом. См. http://luajit.org/ext_ffi_semantics.html#callback.

Ваша функция cpSpaceEachBody принимает функцию в качестве второго параметра. Каждый раз, когда вы это называете; вы создаете новую функцию C.

В дополнение к созданию слишком многих из них; вы никогда не освобождаете их.

Вы должны использовать как можно меньше функций C. В вашем примере вы используете одну и ту же функцию каждый раз, так что это простое исправление:

ffi = require('ffi')
ffi.cdef([[typedef double cpFloat;
typedef struct cpSpace cpSpace;
typedef struct cpBody cpBody;

cpSpace* cpSpaceNew(void);
cpBody* cpBodyNew(cpFloat mass, cpFloat moment);
cpBody* cpSpaceAddBody(cpSpace *space, cpBody *body);

typedef void (*cpSpaceBodyIteratorFunc)(cpBody *body, void *data);
void cpSpaceEachBody(cpSpace *space, cpSpaceBodyIteratorFunc func, void *data);

]])

chipmunk = ffi.load("chipmunk")
space = chipmunk.cpSpaceNew()
body = chipmunk.cpBodyNew(10, 100)
chipmunk.cpSpaceAddBody(space, body)

drawBody = function(body, x) end
drawBody_C_func = ffi.cast("cpSpaceBodyIteratorFunc", drawBody)
CALL_COUNT = 5000
for i = 1, CALL_COUNT do
  chipmunk.cpSpaceEachBody(space, drawBody_C_func, nil)
end
drawBody_C_func:free()
person daurnimator    schedule 25.06.2015