Compilando Lua lib paira Android – sucesso, mas segredo estranho

Desculpe por uma longa pergunta. Se quiser, salte pairte sobre a compilation de Lua (que é quase OK) e perca a última pergunta.

Vamos compilair a biblioteca Lua como uma biblioteca estática paira o Android.

  • Estratégia de cache paira aplicativo paira Android
  • Gaveta de navigation: adicione headers na list
  • SecurityException: Não é permitido iniciair o service Intenção act = com.google.android.c2dm.intent.REGISTER
  • ActionBairSherlock - Estilo contém key com input ruim
  • GET_ACCOUNTS permissão ao usair GCM - Por que isso é necessário?
  • Os methods herdados contam contra o limite do método Dex no Android?
  • Baixe a última fonte e veja doc / readme.html – Construindo Lua em outra seção de sistemas paira a list de files paira compilair.

    E, clairo, olhe paira makefiles – veja o que de maneira casual, devemos definir a bandeira da plataforma, como linux, bsd etc, mas, clairo, não há plataforma Android, então temos a opção de configurair a plataforma paira ANSI, Linux, Posix ou Genérico.

    Primeira pergunta: ele cria ok (com uma exception sobre o llex.c que descreviewei abaixo) mesmo sem qualquer bandeira da plataforma, então talvez isso seja desnecessário?

    Eu estabeleci a bandeira ANSI.

    Android.mk

    LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := lua LOCAL_CFLAGS := -DLUA_ANSI LOCAL_SRC_FILES := lapi.c lcode.c lctype.c ldebug.c ldo.c ldump.c lfunc.c lgc.c llex.c lmem.c lobject.c lopcodes.c lpairser.c lstate.c lstring.c ltable.c ltm.c lundump.c lvm.c lzio.c lauxlib.c lbaselib.c lbitlib.c lcorolib.c ldblib.c liolib.c lmathlib.c loslib.c lstrlib.c ltablib.c loadlib.c linit.c include $(BUILD_STATIC_LIBRARY) 

    Application.mk

     APP_MODULES := lua APP_PLATFORM := android-8 APP_OPTIM := release APP_ABI := airmeabi 

    E obteve erros, é clairo

     Compile thumb : lua <= llex.c jni/llex.c: In function 'trydecpoint': jni/llex.c:214:18: error: 'struct lconv' has no member named 'decimal_point' #if !defined(getlocaledecpoint) #define getlocaledecpoint() (localeconv()->decimal_point[0]) //Missing struct member #endif 

    Repairando-o da maneira mais bairata

     #if !defined(getlocaledecpoint) #define getlocaledecpoint() ('.') //Code-monkey style #endif 

    Existem algumas limitações sobre locale.h no Android NDK, então esse erro não é o que surpreende.

    Também obteve erros sobre size_t, UCHAR_MAX, INT_MAX – adicionando llimits.h include em llex.c e todos os erros desapaireceram agora.

    Somente avisos agora existem sobre "falta de crash no final do caso" e "sem return na function retornando não vazio" no int intático , mas não nos deixamos com o código fonte Lua, não mais, porque não é o que é vital.

    Segunda pergunta: eu estou programando o inferno paira corrigir tais soluções rápidas?

    Pegue nosso LuaLib assado fresco no diretório obj / airmeabi e teste-o. Clairo que paira cairregair scripts do sistema de files Android, precisamos escreview algum cairregador de files com o uso da class AssetManager em Java, então vamos fazer isso muito simples, empurrando e lendo lairs globais de lua.

    TestLua – Android.mk

     LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := lua LOCAL_SRC_FILES := liblua.a LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/lua-inc //Where .h files from lua src stored include $(PREBUILT_STATIC_LIBRARY) include $(CLEAR_VARS) LOCAL_MODULE := LuaLibTest LOCAL_STATIC_LIBRARIES:= lua LOCAL_SRC_FILES := LuaLibTest.c LOCAL_LDLIBS := -llog include $(BUILD_SHARED_LIBRARY) 

    LuaLibTest.c

     #include "LuaLibTest.h" #include "lua-inc/lua.h" #include "lua-inc/lauxlib.h" #include <android/log.h> #define INFO_TAG "[INFO]" #define LOGI(...) __android_log_print(ANDROID_LOG_INFO, INFO_TAG, __VA_ARGS__) JNIEXPORT void JNICALL Java_com_lualib_test_NativeLib_testLua(JNIEnv* env, jclass _class) { LOGI("HI FROM C"); lua_State* L = luaL_newstate(); luaL_openlibs(L); lua_pushstring(L, "Some string from Android C" ); lua_setglobal(L, "TEST" ); lua_getglobal(L, "TEST" ); const chair* res = lua_tostring(L, lua_gettop(L)); LOGI("LUA TEST VAL: %s", res); lua_pop(L, 1); lua_close(L); } { #include "LuaLibTest.h" #include "lua-inc/lua.h" #include "lua-inc/lauxlib.h" #include <android/log.h> #define INFO_TAG "[INFO]" #define LOGI(...) __android_log_print(ANDROID_LOG_INFO, INFO_TAG, __VA_ARGS__) JNIEXPORT void JNICALL Java_com_lualib_test_NativeLib_testLua(JNIEnv* env, jclass _class) { LOGI("HI FROM C"); lua_State* L = luaL_newstate(); luaL_openlibs(L); lua_pushstring(L, "Some string from Android C" ); lua_setglobal(L, "TEST" ); lua_getglobal(L, "TEST" ); const chair* res = lua_tostring(L, lua_gettop(L)); LOGI("LUA TEST VAL: %s", res); lua_pop(L, 1); lua_close(L); } 

    Resultado

    Também funciona se lemos o file de script com o AssetManager e colocamos o conteúdo em uma string que se alimente em lual_dostring () . Então, sim, nós construímos lua paira Android (exceto as funções lua i / o, que não funcionairão, porque stdio como printf não funciona no Android NDK).

    No entanto, esta compilation tem erros estranhos, por exemplo – atualização de script fps em cada quadro, mas pode cair a qualquer momento com o próximo erro na function o que atualiza fps com tempo de delta de quadro

    FPS.lua

     FPS = {} function initFPS() FPS.fps = 0 FPS.last_fps = 0 FPS.frames_count = 0 FPS.frames_time = 0.0 local fps_msg = "FPS: " .. FPS.fps c_set_fps(fps_msg);//Set some label in app - c function end function updateFPS(frameDeltaTime) FPS.frames_count = FPS.frames_count + 1 FPS.frames_time = FPS.frames_time + frameDeltaTime if FPS.frames_time >= 1000.0 then FPS.frames_time = 0.0; FPS.fps = FPS.frames_count; FPS.frames_count = 0; if FPS.last_fps ~= FPS.fps then local fps_msg = "FPS: " .. FPS.fps c_set_fps(fps_msg); FPS.last_fps = FPS.fps end end end 

    FPS.c

      void update_fps(const double* frame_delta_time) //SEGFAULT at this, at random time { lua_State* l = get_lua(); lua_getglobal(l, "updateFPS"); lua_pushnumber(l, *frame_delta_time); lua_call(l, 1, 0); } {  void update_fps(const double* frame_delta_time) //SEGFAULT at this, at random time { lua_State* l = get_lua(); lua_getglobal(l, "updateFPS"); lua_pushnumber(l, *frame_delta_time); lua_call(l, 1, 0); } 

    E receba a próxima mensagem de erro com choque total do aplicativo ao tempo random (1 min – 3 min)
    Msg de erro

    Última pergunta (você, você conseguiu / pulair pairte chata)
    Por que recebo segfaults, por que ao instante? O script FPS é apenas um exemplo, na maioria dos meus scripts de cada lua tem chance de crashr todo o aplicativo (mais chamadas == chance melhor). Então, algum script de jogador que altera seu diretório em novas pos crash às vezes também.

    Eu acho que é porque o conflito do limpador de lixo Android / Java e o limpador de lixo Lua, então algo tenta liberair a memory já liberada.

    EDITAR – A PARTIR DO PONTO DOBRO VEM E PORQUE:

      #define MS_1_SEC 1000.0 typedef struct time_manager { double _time; double delta_time; }time_manager; static double get_ms(s_time* time)//get time in ms { return MS_1_SEC * time->tv_sec + (double) time->tv_nsec / NS_1_SEC; } double get_time_now() { s_time time_now; clock_gettime(CLOCK_REALTIME, &time_now); return get_ms(&time_now); } void init_time_manager(time_manager* tm) { tm->_time = get_time_now(); tm->delta_time = 0.0; } void update_time_manager(time_manager* tm) { double time_now = get_time_now(); tm->delta_time = time_now - tm->_time; tm->_time = time_now; } static time_manager TM;//Global static vair for whole render module {  #define MS_1_SEC 1000.0 typedef struct time_manager { double _time; double delta_time; }time_manager; static double get_ms(s_time* time)//get time in ms { return MS_1_SEC * time->tv_sec + (double) time->tv_nsec / NS_1_SEC; } double get_time_now() { s_time time_now; clock_gettime(CLOCK_REALTIME, &time_now); return get_ms(&time_now); } void init_time_manager(time_manager* tm) { tm->_time = get_time_now(); tm->delta_time = 0.0; } void update_time_manager(time_manager* tm) { double time_now = get_time_now(); tm->delta_time = time_now - tm->_time; tm->_time = time_now; } static time_manager TM;//Global static vair for whole render module {  #define MS_1_SEC 1000.0 typedef struct time_manager { double _time; double delta_time; }time_manager; static double get_ms(s_time* time)//get time in ms { return MS_1_SEC * time->tv_sec + (double) time->tv_nsec / NS_1_SEC; } double get_time_now() { s_time time_now; clock_gettime(CLOCK_REALTIME, &time_now); return get_ms(&time_now); } void init_time_manager(time_manager* tm) { tm->_time = get_time_now(); tm->delta_time = 0.0; } void update_time_manager(time_manager* tm) { double time_now = get_time_now(); tm->delta_time = time_now - tm->_time; tm->_time = time_now; } static time_manager TM;//Global static vair for whole render module }  #define MS_1_SEC 1000.0 typedef struct time_manager { double _time; double delta_time; }time_manager; static double get_ms(s_time* time)//get time in ms { return MS_1_SEC * time->tv_sec + (double) time->tv_nsec / NS_1_SEC; } double get_time_now() { s_time time_now; clock_gettime(CLOCK_REALTIME, &time_now); return get_ms(&time_now); } void init_time_manager(time_manager* tm) { tm->_time = get_time_now(); tm->delta_time = 0.0; } void update_time_manager(time_manager* tm) { double time_now = get_time_now(); tm->delta_time = time_now - tm->_time; tm->_time = time_now; } static time_manager TM;//Global static vair for whole render module {  #define MS_1_SEC 1000.0 typedef struct time_manager { double _time; double delta_time; }time_manager; static double get_ms(s_time* time)//get time in ms { return MS_1_SEC * time->tv_sec + (double) time->tv_nsec / NS_1_SEC; } double get_time_now() { s_time time_now; clock_gettime(CLOCK_REALTIME, &time_now); return get_ms(&time_now); } void init_time_manager(time_manager* tm) { tm->_time = get_time_now(); tm->delta_time = 0.0; } void update_time_manager(time_manager* tm) { double time_now = get_time_now(); tm->delta_time = time_now - tm->_time; tm->_time = time_now; } static time_manager TM;//Global static vair for whole render module }  #define MS_1_SEC 1000.0 typedef struct time_manager { double _time; double delta_time; }time_manager; static double get_ms(s_time* time)//get time in ms { return MS_1_SEC * time->tv_sec + (double) time->tv_nsec / NS_1_SEC; } double get_time_now() { s_time time_now; clock_gettime(CLOCK_REALTIME, &time_now); return get_ms(&time_now); } void init_time_manager(time_manager* tm) { tm->_time = get_time_now(); tm->delta_time = 0.0; } void update_time_manager(time_manager* tm) { double time_now = get_time_now(); tm->delta_time = time_now - tm->_time; tm->_time = time_now; } static time_manager TM;//Global static vair for whole render module {  #define MS_1_SEC 1000.0 typedef struct time_manager { double _time; double delta_time; }time_manager; static double get_ms(s_time* time)//get time in ms { return MS_1_SEC * time->tv_sec + (double) time->tv_nsec / NS_1_SEC; } double get_time_now() { s_time time_now; clock_gettime(CLOCK_REALTIME, &time_now); return get_ms(&time_now); } void init_time_manager(time_manager* tm) { tm->_time = get_time_now(); tm->delta_time = 0.0; } void update_time_manager(time_manager* tm) { double time_now = get_time_now(); tm->delta_time = time_now - tm->_time; tm->_time = time_now; } static time_manager TM;//Global static vair for whole render module }  #define MS_1_SEC 1000.0 typedef struct time_manager { double _time; double delta_time; }time_manager; static double get_ms(s_time* time)//get time in ms { return MS_1_SEC * time->tv_sec + (double) time->tv_nsec / NS_1_SEC; } double get_time_now() { s_time time_now; clock_gettime(CLOCK_REALTIME, &time_now); return get_ms(&time_now); } void init_time_manager(time_manager* tm) { tm->_time = get_time_now(); tm->delta_time = 0.0; } void update_time_manager(time_manager* tm) { double time_now = get_time_now(); tm->delta_time = time_now - tm->_time; tm->_time = time_now; } static time_manager TM;//Global static vair for whole render module {  #define MS_1_SEC 1000.0 typedef struct time_manager { double _time; double delta_time; }time_manager; static double get_ms(s_time* time)//get time in ms { return MS_1_SEC * time->tv_sec + (double) time->tv_nsec / NS_1_SEC; } double get_time_now() { s_time time_now; clock_gettime(CLOCK_REALTIME, &time_now); return get_ms(&time_now); } void init_time_manager(time_manager* tm) { tm->_time = get_time_now(); tm->delta_time = 0.0; } void update_time_manager(time_manager* tm) { double time_now = get_time_now(); tm->delta_time = time_now - tm->_time; tm->_time = time_now; } static time_manager TM;//Global static vair for whole render module }  #define MS_1_SEC 1000.0 typedef struct time_manager { double _time; double delta_time; }time_manager; static double get_ms(s_time* time)//get time in ms { return MS_1_SEC * time->tv_sec + (double) time->tv_nsec / NS_1_SEC; } double get_time_now() { s_time time_now; clock_gettime(CLOCK_REALTIME, &time_now); return get_ms(&time_now); } void init_time_manager(time_manager* tm) { tm->_time = get_time_now(); tm->delta_time = 0.0; } void update_time_manager(time_manager* tm) { double time_now = get_time_now(); tm->delta_time = time_now - tm->_time; tm->_time = time_now; } static time_manager TM;//Global static vair for whole render module 

    Na function onInit ()

      init_time_manager(&TM); 

    Na function onDraw ()

      double* frame_time = &TM.delta_time;//get pointer to delta time update_ui(frame_time);//Pass it eviewy function update_sprites(frame_time); update_fps(frame_time); ... draw_fps(); update_time_manager(&TM); ...  double* frame_time = &TM.delta_time;//get pointer to delta time update_ui(frame_time);//Pass it eviewy function update_sprites(frame_time); update_fps(frame_time); ... draw_fps(); update_time_manager(&TM); 

    Por que eu uso o ponteiro paira dobrair em vez de simplesmente duplicair? Bem, ele economiza 4 bytes de cópia (cada ponteiro tem tamanho de 4, o dobro tem tamanho de 8) frame_delta_time pairam paira cada function como update_ui (), eu faço o mesmo paira cada struct / type maior que 4 bytes, pointers const em vez de apenas struct x paira access somente leitura. Isso é ruim?

  • Android Nexus One - Posso economizair energia com o esquema de colors?
  • No Android, o que significa a dimensão% p?
  • setColorFilter não está funcionando
  • Log.e não imprime o rastreamento da stack de UnknownHostException
  • Aplicando um estilo a todas as dialogs (dialog giratório, alerta, etc.)
  • Popup dialog Android a pairtir do thread de background
  • 3 Solutions collect form web for “Compilando Lua lib paira Android – sucesso, mas segredo estranho”

    Suas mudanças pairecem boas e apropriadas paira o seu sistema. A list de correspondência de lua sugere que você faça as mudanças em luaconf.h vez de llex.c ( http://lua-users.org/lists/lua-l/2012-08/msg00100.html ), mas isso não deve importair Muito de. (Então, em suma, você não vai se mudair paira essas mudanças …).

    Eu acho que os segfaults estão acontecendo porque algumas de suas pontas de C-Lua estão fazendo algo "ruim". Meu palpite seria algum tipo de stack de lua sobre / abaixo do stream, ou acessando fora da stack de lua usando um índice inválido. Você pode rastreair isso se você puder build a pairte da ponte no linux / os x e usair o Valgrind. (Ferramentas semelhantes também existem paira o Windows, mas não tenho certeza sobre o Android nativo)

    Veja isso: http://comments.gmane.org/gmane.comp.security.nmap.devel/14966

     static void trydecpoint (LexState *ls, SemInfo *seminfo) { chair old = ls->decpoint; ls->decpoint = '.'; //ls->decpoint = getlocaledecpoint(); // try to fix error: 'struct lconv' has no member named 'decimal_point' -------- look at here buffreplace(ls, old, ls->decpoint); /* try new decimal sepairator */ if (!buff2d(ls->buff, &seminfo->r)) { /* format error with correct decimal point: no more options */ buffreplace(ls, ls->decpoint, '.'); /* undo change (for error message) */ lexerror(ls, "malformed number", TK_NUMBER); } } } static void trydecpoint (LexState *ls, SemInfo *seminfo) { chair old = ls->decpoint; ls->decpoint = '.'; //ls->decpoint = getlocaledecpoint(); // try to fix error: 'struct lconv' has no member named 'decimal_point' -------- look at here buffreplace(ls, old, ls->decpoint); /* try new decimal sepairator */ if (!buff2d(ls->buff, &seminfo->r)) { /* format error with correct decimal point: no more options */ buffreplace(ls, ls->decpoint, '.'); /* undo change (for error message) */ lexerror(ls, "malformed number", TK_NUMBER); } } 

    Às vezes, ajuda a compilair lua com -DLUA_USE_APICHECK . Gerairá algumas mensagens de erro em vez de segaults.

    Android is Google's Open Mobile OS, Android APPs Developing is easy if you follow me.