COCOS2DX Android Run Luac compiled LUA code

Source: Internet
Author: User
Tags lua

Operating Environment

Win7 64

cocos2d-2.1rc0-x-2.1.2

LUA 5.1

Usually we write good LUA code is clear form, anyone can see the changes, in order to prevent their labor results are not easily stolen by others, you can use LUAC (LUA library) to encrypt it, converted to binary files. This will not allow the LUA code to be viewed directly, but there is a problem: it works well under windows and is black on Android, prompting for errors:
[LUA ERROR] binary string:unexpected end in precompiled chunk


Traced


View the LUA load code in BOOL Appdelegate::applicationdidfinishlaunching ():

#if (Cc_target_platform = = cc_platform_android)    ccstring* pstrfilecontent = Ccstring::createwithcontentsoffile (" Program/main.lua ");    if (pstrfilecontent)    {        pengine->executestring (pstrfilecontent->getcstring ());    } #else            std::string Path = Ccfileutils::sharedfileutils ()->fullpathforfilename ("Program/main.lua");    Pengine->addsearchpath (path.substr (0, path.find_last_of ("/")). C_str ());    Pengine->executescriptfile (Path.c_str ()); #endif

Here executestring () loads LUA files and continues to see what the source of the real work is:

LUALIB_API int Lual_loadbuffer (lua_state *l, const char *buff, size_t size,                                const char *name) {  LoadS ls;  LS.S = buff;  ls.size = size;  Return Lua_load (L, GetS, &ls, name);}

Look back at the execution of the function executescriptfile ():

LUALIB_API int Lual_loadfile (lua_state *l, const char *filename) {LOADF lf;  int status, Readstatus;  int C;  int fnameindex = Lua_gettop (L) + 1;  /* Index of filename on the stack */lf.extraline = 0;    if (filename = = NULL) {lua_pushliteral (L, "=stdin");  LF.F = stdin;    } else {lua_pushfstring (L, "@%s", filename);    LF.F = fopen (filename, "R");  if (lf.f = = NULL) return Errfile (L, "open", Fnameindex);  } c = Getc (LF.F);    if (c = = ' # ') {/* Unix exec. File */lf.extraline = 1;  while ((c = getc (LF.F))! = EOF && c! = ' \ n ');  /* Skip First line */if (c = = ' \ n ') c = getc (LF.F);  } if (c = = lua_signature[0] && filename) {/* binary file? */lf.f = freopen (filename, "RB", LF.F);    /* Reopen in binary mode */if (LF.F = = NULL) return Errfile (L, "reopen", Fnameindex);    /* Skip eventual ' #!... ' * * while ((c = getc (LF.F))! = EOF && c! = lua_signature[0]);  Lf.extraline = 0;  } ungetc (c, LF.F); Status = Lua_load (L, GETF, & LF, lua_tostring (L,-1));  The key, as in Lual_loadbuffer () Readstatus = Ferror (LF.F);  if (filename) fclose (LF.F);  /* Close file (even in case of errors) */if (readstatus) {lua_settop (L, Fnameindex);  /* Ignore results from ' lua_load ' */return Errfile (L, "read", Fnameindex);  } lua_remove (L, Fnameindex); return status;}
Note The Chinese comment section of the code, which explains why files compiled with LUAC can be run well under Windows (iOS is OK), but not on Android. Lual_loadfile () Determines whether LUA files are encrypted by c = = Lua_signature[0], and if so, re-opens in "RB" mode.


Solutions

Modify the Loader_android () function in Scripting\lua\cocos2dx_support\cocos2dxlualoader.cpp

Before modification:

int loader_android (lua_state *l)    {        std::string filename (lual_checkstring (L, 1));        Filename.append (". Lua");        ccstring* pfilecontent = Ccstring::createwithcontentsoffile (Filename.c_str ());        if (pfilecontent)        {            if (lual_loadstring (L, pfilecontent->getcstring ())! = 0)            {                lual_error (L, " Error loading module%s from file%s: \n\t%s ",                    lua_tostring (L, 1), Filename.c_str (), lua_tostring (L,-1));            }        }        else        {            Cclog ("Can not get file data of%s", Filename.c_str ());        }        return 1;    }

After modification:

int loader_android (lua_state* L) {unsigned char* pData = nullptr;unsigned long size = 0;/* Modify for read Lua script from Bytecode */std::string filename (lual_checkstring (L, 1)), std::string rel_name = Filename.append (". Lua");pD ATA = Ccfileutils::sharedfileutils ()->getfiledata (Rel_name.c_str (), "RB", &size), if (PData) {if (Lual_loadbuffer (L , (char*) pdata,size,rel_name.c_str ())! = 0) {lual_error (L, "error loading module s from File S:s", Lua_tostring (L, 1), RE L_name.c_str (), lua_tostring (L,-1));}} else {Cclog ("Can not get file data of%s", Filename.c_str ());} Cc_safe_delete_array (PData); return 1;}

Also, since the first time that LUA is loaded in CPP does not call Loader_android (), this is because Ual_loadbuffer only loads the file into a chunk and does not run the chunk, so add a tune to the name Lua_pcall, As follows:

int loader_android (lua_state* L) {unsigned char* pData = nullptr;unsigned long size = 0;/* Modify for read Lua script from Bytecode */std::string filename (lual_checkstring (L, 1)), std::string rel_name = Filename.append (". Lua");pD ATA = Ccfileutils::sharedfileutils ()->getfiledata (Rel_name.c_str (), "RB", &size), if (PData) {if (Lual_loadbuffer (L , (char*) pdata,size,rel_name.c_str ())! = 0 | | Lua_pcall (l, 0, Lua_multret, 0)) {//Modify place Lual_error (L, "error loading module s from File S:s", Lua_tostring (L, 1), Rel_na Me.c_str (), lua_tostring (L,-1));}} else {Cclog ("Can not get file data of%s", Filename.c_str ());} Cc_safe_delete_array (PData); return 1;}
Or we could steal a chicken,

Pengine->executestring ("Require \" program/main\ ""); Note that the \ "

The last of our appdelegate::applicationdidfinishlaunching () is probably like this,

    Const char* Luafile = "Program/main.lua"; #if (cc_target_platform = = cc_platform_android) std::string path = CCFileUtils:: Sharedfileutils ()->fullpathforfilename (luafile); Cclog ("Path =%s", Path.c_str ()), std::string subpath = path.substr (0, path.find_last_of ("/")); Cclog ("Sub path =%s", Subpath.c_str ());p Engine->addsearchpath (Subpath.c_str ());std::vector<std::string> Searchpaths = Ccfileutils::sharedfileutils ()->getsearchpaths () Searchpaths.insert (SearchPaths.begin (), SubPath ); Ccfileutils::sharedfileutils ()->setsearchpaths (searchpaths);p engine->executestring ("Require \" program/ Main\ ""); Note here the \ "#else            std::string Path = Ccfileutils::sharedfileutils ()->fullpathforfilename (luafile);    Pengine->addsearchpath (path.substr (0, path.find_last_of ("/")). C_str ());    Pengine->executescriptfile (Path.c_str ()); #endif

Note: Here the author stole the chicken a bit.


Reference reference

http://www.cocos2d-x.org/forums/11/topics/28628

Http://www.cnblogs.com/mrblue/archive/2013/06/06/3122543.html




Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.