编译Lua的lib中Android的 - 成功,但奇怪的段错误奇怪、错误、Lua、lib

2023-09-04 11:13:21 作者:十里承欢

抱歉长的问题。如果你想跳过部分有关编译Lua的(几乎确定),并获得直接到最后一个问题。的

让我们编译的Lua库就像一个静态库为Android。

Let's compile Lua library like a static library for Android.

下载最新的源代码,并期待到DOC / readme.html文件 - 建筑Lua中的其他系统上的部分文件列表编译

Download latest source and look into doc/readme.html - Building Lua on other systems section for list of files to compile.

当然考虑的makefile - 看到休闲的方式是什么,我们必须设置平台标志等是linux,BSD等当然,但没有Android平台,所以我们选择设置平台,以ANSI,Linux和Posix的或通用。

And of course look into makefiles - see what in casual way we must set platform flag such is linux, bsd e.t.c. But of course there is no Android platform, so we have choice to set platform to ANSI, Linux, Posix or Generic.

第一个问题:它建立正常(有一个例外约llex.c我将描述楼下),即使没有任何平台的标志,所以也许这是不必要的。

First question: it builds ok (with one exception about llex.c which i will describe down below) even without any platform flag, so maybe this unnecessary?

我设置的ANSI标志。

I set ANSI flag.

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 lparser.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 := armeabi

和得到,当然错误

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

修复它以最廉价的方式

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

有一些限制的 locale.h文件在Android的NDK,所以这个错误不是什么奇怪了。

There are some limitations about locale.h in Android NDK, so this error is not what surprising.

也得到了有关的size_t错误,UCHAR_MAX,INT_MAX - 增加 llimits.h 包含到llex.c和所有的错误,现在都没有了。

Also got errors about size_t, UCHAR_MAX, INT_MAX - adding llimits.h include into llex.c and all errors are gone now.

只有警告现在存在约的的情况下丢掉了破发和在功能上没有返回返回非空,在的静态INT llex ,但我们不要乱用Lua的源$ C ​​$ C没有更多的,因为这不是什么重要的。

Only warnings now exist about "missing break at the end of case" and "no return in function returning non-void" in static int llex, but we don't mess with Lua source code no more because it's not what vital.

第二个问题:我该怎么程序员地狱这种快速修复

Second Question: am i going to programmer hell for such quick fixes?

抢我们的新鲜出炉LuaLib在 OBJ / armeabi 目录,让测试它。 当然加载从Android文件系统中的脚本,我们需要写一些文件加载​​器与在Java中使用AssetManager类的,所以让我们做到这一点远远推和阅读LUA全局变量的简单。

Grab our fresh baked LuaLib in obj/armeabi directory and lets test it. Of course to load scripts from android file system, we need write some file loader with use of AssetManager class in Java, so let's do it far simple by pushing and reading lua global vars.

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 char* res = lua_tostring(L, lua_gettop(L));
 LOGI("LUA TEST VAL: %s", res);
 lua_pop(L, 1);
 lua_close(L);
}

这也适用,如果我们读AssetManager脚本文件,并把它的内容到字符串,它送入 lual_dostring()。所以,是的,我们建立LUA为Android(除LUA I / O功能,这是行不通的,因为STDIO如printf不会在Android的NDK的工作)。

It also works if we read script file with AssetManager and put it contents in to string which feed into lual_dostring(). So yes, we build lua for Android (except lua i/o functions, which will not work, because stdio like printf don't work in Android NDK).

不过这个版本有奇怪的错误,例如 - FPS脚本更新每一帧,但它可以落在任何时刻与在功能的下一个错误是什么更新fps的帧增量时间

However this build have strange errors, for example - fps script update every frame, but it can fall at any moment with next error at function what updates fps with frame delta time

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);
 }

和获得与整个应用程序崩溃,在随机时间一个错误信息(1分钟 - 3分钟)

And get next error message with whole app crash at random time (1 min - 3 min)

最后一个问题(耶,你来了/跳过枯燥的部分) 为什么我得到段错误,为什么在随机时间? FPS脚本只是例子,顶多我的每一个LUA脚本有机会崩溃整个应用程序(多打几个电话==更好的机会)。因此,一些球员脚本,改变它的目录,在新的POS崩溃有时太。

Last question (yay, you made it/skip boring part) Why I get segfaults, why at random time? FPS script is just example, at most my every lua script has chance to crash whole app (more calls==better chance). So some player script which change its dir at new pos crash sometimes too.

我想这是因为Android的/ Java的垃圾清除器和Lua的垃圾清除器的冲突,所以一些尝试释放已经释放的内存。

I think it's because conflict of Android/Java garbage cleaner and Lua garbage cleaner, so something try to free already freed memory.

编辑 - 从那里双指针来,原因:

 #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 var for whole render module

中的OnInit()函数

 init_time_manager(&TM);

中的OnDraw()函数

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

为什么我用指向double而不是仅仅增加一倍?那么它可以节省4个字节的复制(每个指针有4个尺寸,双有8个大小)frame_delta_time参数像update_ui每个函数(),我做相同的每个结构/类型大于4个字节,const的指针,而不是只结构x对于只读访问。这是一件坏事吗?

Why i use pointer to double instead of just double? Well it saves 4 bytes of copying (every pointer has size of 4, double has size of 8) frame_delta_time param to every function like update_ui(), i do the same for every struct/type bigger than 4 bytes, const pointers instead of just struct x for read-only access. Is this bad thing?

推荐答案

您更改一下确定,适合您的系统。 lua的邮件列表,建议您进行更改 luaconf.h ,而不是 llex.c (http://lua-users.org/lists/lua-l/2012-08/msg00100.html ),但它不应该的问题多。 (因此,在短期,你不会下地狱这些变化......)。

Your changes look OK and appropriate for your system. The lua mailing list suggests that you make the changes to luaconf.h rather than llex.c ( http://lua-users.org/lists/lua-l/2012-08/msg00100.html ) but it shouldn't matter much. (So in short you're not going to hell for these changes ... ).

我猜的内存设计缺陷的发生,因为你的一些C-LUA桥是做一些坏。我的猜测是某种形式的Lua堆栈上/下流量,或者使用无效​​的索引访问LUA堆栈之外。您可以跟踪下来,如果你能建立在Linux / OS X和使用的valgrind桥的一部分。 (类似的工具的Windows存在过,但我不知道有关本机到Android)

I'm guessing that the segfaults are happening because some of your C-lua bridge is doing something "bad". My guess would be some kind of lua stack over/under flow, or accessing outside the lua stack by using an invalid index. You may be able to track this down if you can build the bridge part on linux/os x and use valgrind. (Similar tools exist for windows too, but I'm not sure about native to android)