Skip to content

Latest commit

 

History

History
279 lines (193 loc) · 7.59 KB

luaIntegrate.md

File metadata and controls

279 lines (193 loc) · 7.59 KB

...menustart

...menuend

Integrate LUA

1. include lua header files

extern "C" {
#include "lua.h"
#include "lualib.h"
#include "lauxlib.h"
}

2. create your lua state class

    LuaState::LuaState(void) {
    }


    LuaState::~LuaState(void) {
    }

    void LuaState::Init() {
        L = lua_open();
        // load the libs
        luaL_openlibs(L);
    }

3. print problem

  • sometime lua print function will not output to your engine's console
namespace {
int lua_print(lua_State * luastate) {
    int nargs = lua_gettop(luastate);

    std::string t;
    for (int i=1; i <= nargs; i++)
    {
        if (lua_istable(luastate, i))
            t += "table";
        else if (lua_isnone(luastate, i))
            t += "none";
        else if (lua_isnil(luastate, i))
            t += "nil";
        else if (lua_isboolean(luastate, i))
        {
            if (lua_toboolean(luastate, i) != 0)
                t += "true";
            else
                t += "false";
        }
        else if (lua_isfunction(luastate, i))
            t += "function";
        else if (lua_islightuserdata(luastate, i))
            t += "lightuserdata";
        else if (lua_isthread(luastate, i))
            t += "thread";
        else
        {
            const char * str = lua_tostring(luastate, i);
            if (str)
                t += lua_tostring(luastate, i);
            else
                t += lua_typename(luastate, lua_type(luastate, i));
        }
        if (i!=nargs)
            t += "\t";
    }
    // HERE , replace with your engine's log function
    CCLOG("[LUA-print] %s", t.c_str());

    return 0;
}
}  // namespace {
  • register lua_print
    // Register our version of the global "print" function
    const luaL_reg global_functions [] = {
        {"print", lua_print},
        {NULL, NULL}
    };
    luaL_register(m_state, "_G", global_functions);

4. add lua search path

void LuaState::addSearchPath(const char* path)
{
    lua_getglobal(m_state, "package");                                  /* L: package */
    lua_getfield(m_state, -1, "path");                /* get package.path, L: package path */
    const char* cur_path =  lua_tostring(m_state, -1);
    lua_pushfstring(m_state, "%s;%s/?.lua", cur_path, path);            /* L: package path newpath */
    lua_setfield(m_state, -3, "path");          /* package.path = newpath, L: package path */
    lua_pop(m_state, 2);                                                /* L: - */
}

5. tolua++

  • tolua

  • tolua_fix.h/c

  • after exporting files via tolua, you should add the generated function TOLUA_API int tolua_onyx_plus_open (lua_State* tolua_S); to your Lua_state init function.

  • tolua 传递 userdata 总是使用 指针,然后做相应的必须转换 *ptr

template

https://www8.cs.umu.se/kurser/TDBD12/VT04/lab/lua/tolua++.html

  • 使用 TEMPLATE_BIND 实例化多个 binding

  • 目前只支持 class level ,

    • function level not support yet
  • example

struct TEST_A
{
    Vector<LeaderBoardItem> m_LB_items ;
};
  • 假设我们导出了 如上的 struct 的 m_LB_items 字段, 我们要对 m_LB_items 做 push_back 操作
    • 因为 m_LB_items 是 Vector<LeaderBoardItem> 范型, 我们需要 对 Vector 类做 TEMPLATE_BIND
class Vector {
    TEMPLATE_BIND(T,  LeaderBoardItem  )

    void push_back(const T& element);
} ;

name space

  • call by lua
namespace.classname:functionname( ... )

enumerate

  • pkg 文件 函数声明 有用到 enum的情况,需要把 enum的定义也放入 pkg 文件

struct

  • C++
    • only classes (and structs) with a constructor will have a 'new()' method
    • You can add the constructor on your pkg (even if it's not actually implemented).
  • C
    • the only solution I can think of is to have a function that creates a new struct and returns it

6. c++ reigster lua callback

  • 使用 cocos2dx 的 tolua-fix 方法
  • 在 .pkg 文件中, 使用 LUA_FUCNTION ( 实质是一个 int 类型 ) 声明一个handle
    • void registerScriptHandler(int handler);
  • tolua-fix 会 处理成一个 lua function ref
    • LUA_FUNCTION handler = ( toluafix_ref_function(tolua_S,2,0));
  • 在 c++ 代码中 保存这个handle, 然后,使用 executeFunctionByHandler 来执行这个函数
  • lua 方面的相关调用
    local shs = ScriptHandlerSample()
    shs:registerScriptHandler( function()  print("lua callback");  end )

7. lua / c++

  • c++ 获取 lua 方法 返回值 , 或 变量值
  • cocos2dx 提供 executeString 可以完成大部分事情
    1. 执行一段lua 代码
      • executeString( "lua_code_string" )
    2. 获取 lua 变量值 (目前值支持 number/boolean 返回)
      • executeString ( "require 'modulename' ;return modulename.varname" )
    3. 获取 lua 函数返回值
      • executeString ( "require 'modulename' ;return modulename.funcname()" )

8. lua / Java

  • https://segmentfault.com/a/1190000004252394
  • android 平台的线程问题
    • 一般 lua会在 非UI working 线程中调用 (如 GL线程)
    • java 的一些callback,一般都是在 UI线程中执行,这时如果要调用lua方法,就需要 在正确的线程中调用
    • 如果可以容忍阻塞,可以使用 线程安全的 ConcurrentLinkedQueue, 在 GL线程中把结果取回,再调用 lua 方法

lua 调用 Java

  • cocos2dx 提供了 luaj.callStaticMethod , 可以 调用 静态java 方法

java 调用 lua

    1. 使用 cocos2dx 提供的 callLuaGlobalFunctionWithString 直接调用 全局lua 方法
    1. 使用 cocos2dx 提供的 callLuaFunctionWithString, 通过 luaFunctionId 来调用 保存的 lua 方法
    • 调用两次 java 方法
    • 第一次, 注册 lua 方法,
      • lua方法作为 参数 调用java 方法, c++层做处理, java 方法只需要 final int luaFunc 接受
    • 第二次, 调用 业务 Java 方法, 在这个业务java 方法中,使用 callLuaFunctionWithString 来调用 lua