woaidaima2016 发表于 2025-10-29 22:28:43

C++调用LuaJit的Demo

头文件

#pragma once

extern "C"
{
#include <luajit/src/lua.h>
#include <luajit/src/lualib.h>
#include <luajit/src/lauxlib.h>
#include <luajit/src/luajit.h>
}

class ScriptVM
{
public:
        ScriptVM();
        ~ScriptVM();

        bool Init();
        void Destroy();
        void ExecuteScriptFile(const char* sScriptName, bool bForceReload = false, bool bAssertOnError = true);
        //void ExecuteScript(const char* sScript, bool bAssertOnError = true);
protected:
        bool LoadFileToBuffer(const std::string& path, std::vector<uint8_t>& buffer);
private:
        lua_State* m_pLua;
};

源文件

#include "pch.h"
#include "script_vm.h"

static int wrap_exceptions(lua_State* L, lua_CFunction f)
{
      try
      {
                return f(L);// Call wrapped function and return result.
      }
      catch (const char* s)
      {
                // Catch and convert exceptions.
                lua_pushstring(L, s);
      }

      catch (std::exception& e)
      {
                lua_pushstring(L, e.what());
      }

      catch (...)
      {
                lua_pushliteral(L, "caught (...)");
      }

      return lua_error(L);// Rethrow as a Lua error.
}

static void error_msg(bool bUseAssert, const char* pacFmt, ...)
{
      //#if defined(_DEBUG)
      char acTemp;

      va_list args;
      va_start(args, pacFmt);
      vsprintf_s(acTemp, pacFmt, args);
      va_end(args);
      if (bUseAssert)
      {
                assert(acTemp);
      }
      //#endif
}

void report_last_error(lua_State* pLua, bool bUseAssert)
{
      lua_getglobal(pLua, "_ALERT");
      error_msg(bUseAssert, "%s\n", lua_tostring(pLua, -2));
      error_msg(bUseAssert, "%s\n", lua_tostring(pLua, -1));
      lua_pop(pLua, 2);/* remove error_msg message and _ALERT */
}

std::string& std_string_format(std::string& _str, const char* _Format, ...)
{
      std::string tmp;

      va_list marker = NULL;
      va_start(marker, _Format);

      size_t num_of_chars = _vscprintf(_Format, marker);

      if (num_of_chars > tmp.capacity())
      {
                tmp.resize(num_of_chars + 1);
      }

      vsprintf_s((char*)tmp.data(), tmp.capacity(), _Format, marker);

      va_end(marker);

      _str = tmp.c_str();
      return _str;
}

ScriptVM::ScriptVM()
{
}

ScriptVM::~ScriptVM()
{
}

int PrintStringList(lua_State* pLuaState)
{
      luaJIT_setmode(pLuaState, -1, LUAJIT_MODE_ALLFUNC | LUAJIT_MODE_ALLSUBFUNC | LUAJIT_MODE_ON);
      // Get the number of strings

      int iStringCount = lua_gettop(pLuaState);

      // Loop through each string and print it, followed by a newline

      for (int iCurrStringIndex = 1; iCurrStringIndex <= iStringCount; ++iCurrStringIndex)
      {
                // First make sure that the current parameter on the stack is a string

                if (!lua_isstring(pLuaState, 1))
                {
                        // If not, print an error

                        lua_error(pLuaState);
                }
                else
                {
                        // Otherwise, print a tab, the string, and finally a newline

                        printf("\t");
                        printf(lua_tostring(pLuaState, iCurrStringIndex));
                        printf("\n");
                }
      }

      // Return zero, as this function does not return any results

      return 0;
}

bool ScriptVM::Init()
{
      m_pLua = luaL_newstate();

      lua_cpcall(m_pLua, luaopen_base, 0);

      lua_cpcall(m_pLua, luaopen_io, 0);

      lua_cpcall(m_pLua, luaopen_string, 0);

      lua_cpcall(m_pLua, luaopen_table, 0);

      lua_cpcall(m_pLua, luaopen_math, 0);

      lua_cpcall(m_pLua, luaopen_debug, 0);

      lua_cpcall(m_pLua, luaopen_os, 0);

      lua_cpcall(m_pLua, luaopen_package, 0);

      //luaopen_base(m_pLua);

      //luaopen_io(m_pLua);

      //luaopen_table(m_pLua);

      //luaopen_math(m_pLua);

      //luaopen_string(m_pLua);

      //luaopen_debug(m_pLua);

      //tolua_open_binding(m_pLua);

      //lua_setgcthreshold(m_pLua, 200); //200k garbage collection threshold

      lua_register(m_pLua, "PrintStringList", PrintStringList);

      //lua_register(m_pLua, "dofile", OverrideDofile);

      // 添加 LuaJIT 的支持
      lua_pushlightuserdata(m_pLua, (void*)wrap_exceptions);
      luaJIT_setmode(m_pLua, 0, LUAJIT_MODE_ENGINE | LUAJIT_MODE_ON);

      return true;
}

void ScriptVM::Destroy()
{
      lua_close(m_pLua);
}

bool ScriptVM::LoadFileToBuffer(const std::string& path, std::vector<uint8_t>& buffer)
{
      std::ifstream file(path, std::ios::binary | std::ios::ate);
      if (!file.is_open())
                return false;

      std::streamsize size = file.tellg();
      if (size <= 0)
                return false;

      buffer.resize(static_cast<size_t>(size));
      file.seekg(0, std::ios::beg);
      if (!file.read(reinterpret_cast<char*>(buffer.data()), size))
                return false;

      return true;
}


void ScriptVM::ExecuteScriptFile(const char* sScriptName, bool bForceReload /* = false*/, bool bAssertOnError /*= true*/)
{
         // 添加 LuaJIT 的支持
         luaJIT_setmode(m_pLua, -1, LUAJIT_MODE_ALLFUNC | LUAJIT_MODE_ALLSUBFUNC | LUAJIT_MODE_ON);

         int nSize1 = lua_gettop(m_pLua);
         //get chunk name as modified script name
         std::string sChunkName(sScriptName);
         for (unsigned int i = 0; i < sChunkName.length(); i++)
         {
               if (sChunkName == '/' || sChunkName == '.')
                         sChunkName = '_';
         }

         //get the chunk global
         lua_getglobal(m_pLua, sChunkName.c_str());
         if (bForceReload || !lua_isfunction(m_pLua, -1))//if force reload or not found
         {
               //load it first
                std::vector<uint8_t> Buffer;

               if (LoadFileToBuffer(sScriptName, Buffer))
               {
                         luaL_loadbuffer(m_pLua, (char*)Buffer.data(), Buffer.size(), sScriptName);

                         //            luaL_loadfile(m_pLua, sScriptName);
                         lua_setglobal(m_pLua, sChunkName.c_str());
                         lua_getglobal(m_pLua, sChunkName.c_str());
               }
               else
                         goto failed;
         }

         if (lua_pcall(m_pLua, 0, 0, 0) != 0)
         {
               error_msg(bAssertOnError, "error executing script file %s: ", sScriptName);
               report_last_error(m_pLua, bAssertOnError);
         }

failed:
         lua_settop(m_pLua, nSize1);
}

//
// void ScriptVM::ExecuteScript(const char* sScript, bool bAssertOnError)
// {
//         // 添加 LuaJIT 的支持
//         luaJIT_setmode(m_pLua, -1, LUAJIT_MODE_ALLFUNC | LUAJIT_MODE_ALLSUBFUNC | LUAJIT_MODE_ON);
//
//         int status = luaL_loadbuffer(m_pLua, sScript, strlen(sScript), sScript);
//
//         if (status)
//         {
//               //report_last_error(m_pLua, bAssertOnError);
//         }
//         else
//         {
//               status = lua_pcall(m_pLua, 0, LUA_MULTRET, 0);/* call main */
//
//               //if (status)
//               //      report_last_error(m_pLua, bAssertOnError);
//         }
// }
//
// bool ScriptVM::ExecuteScriptFunc(const std::vector<const char*>& modules, const char* func, bool bAllowNonexist, const char* sig, ...)
// {
//         // 添加 LuaJIT 的支持
//         luaJIT_setmode(m_pLua, -1, LUAJIT_MODE_ALLFUNC | LUAJIT_MODE_ALLSUBFUNC | LUAJIT_MODE_ON);
//
//         bool bIsSuccess = false;
//
//         //PROFILE("ExecuteScriptFunc");
//
//         int nSize1 = lua_gettop(m_pLua);
//
//         //debug
//
// #if DEBUG_STACK
//         printf("debug lua: stack size before ExecuteScriptFunc = %d\n", nSize1);
// #endif
//
//         va_list    vl;
//         int    narg, nres;    /* number of arguments and results */
//         va_start(vl, sig);
//
//         //get the actual function
//         if (modules.empty()) //func is global
//         {
//               lua_getglobal(m_pLua, func);
//
//               if (!lua_isfunction(m_pLua, -1))
//               {
//                         if (!bAllowNonexist)
//                                 error_msg(true, "ExecuteScriptFunc: Invalid function name: %s\n", func);
//
//                         goto failed;
//               }
//         }
//         else
//         {
//
//               //trace down the modules
//
//               std::vector<const char*>::const_iterator it = modules.begin();
//
//               //get the global module name or the actual function name if there is no module
//
//               lua_getglobal(m_pLua, *it);
//
//               if (!lua_istable(m_pLua, -1))
//
//               {
//
//                         if (!bAllowNonexist)
//
//                                 error_msg(true, "ExecuteScriptFunc: Invalid table name: %s\n", *it);
//
//                         goto failed;
//
//               }
//
//
//
//               for (++it; it != modules.end(); ++it)
//
//               {
//
//                         lua_pushstring(m_pLua, *it);
//
//                         lua_gettable(m_pLua, -2);
//
//                         if (!lua_istable(m_pLua, -1))
//
//                         {
//
//                                 if (!bAllowNonexist)
//
//                                       error_msg(true, "ExecuteScriptFunc: Invalid table name: %s\n", *it);
//
//                                 goto failed;
//
//                         }
//
//               }
//
//               //get the func
//
//               lua_pushstring(m_pLua, func);
//
//               lua_gettable(m_pLua, -2);
//
//               if (!lua_isfunction(m_pLua, -1))
//
//               {
//
//                         if (!bAllowNonexist)
//
//                                 error_msg(true, "ExecuteScriptFunc: Invalid function name: %s\n", func);
//
//                         goto failed;
//
//               }
//
//         }
//
//
//
//         /* push    arguments */
//
//         narg = 0;
//
//         while (*sig) { /* push arguments    */
//
//               switch (*sig++) {
//
//               case 'd': /* double    argument */
//
//               case 'f': /* float    argument */    // NieXu: Treat float as double, same as printf()
//
//                         lua_pushnumber(m_pLua, va_arg(vl, double));
//
//                         break;
//
//               case 'i': /* int argument */
//
//                         lua_pushnumber(m_pLua, va_arg(vl, int));
//
//                         break;
//
//               case 's': /* string    argument */
//
//                         lua_pushstring(m_pLua, va_arg(vl, char*));
//
//                         break;
//
//               case 'b': /* boolean argument */
//
//                         lua_pushboolean(m_pLua, va_arg(vl, bool));
//
//                         break;
//
//               case 'u': /* light user data */
//
//                         lua_pushlightuserdata(m_pLua, va_arg(vl, void*));
//
//                         break;
//
//               case 't': /* type user data */
//
//               {
//
//                         void* pData = va_arg(vl, void*);
//
//                         const char* sType = va_arg(vl, const char*);
//
//                         tolua_pushusertype(m_pLua, pData, sType);
//
//                         break;
//
//               }
//
//
//
//               case '>':
//
//                         goto endwhile;
//
//               default:
//
//                         error_msg(true, "invalid option (%c)\n", *(sig - 1));
//
//                         goto failed;
//
//               }
//
//               narg++;
//
//               luaL_checkstack(m_pLua, 1, "too many    arguments");
//
//         }endwhile:
//
//         /* do the call */
//
//         nres = strlen(sig);    /* number of expected results */
//
//         if (lua_pcall(m_pLua, narg, nres, 0) != 0) /* do    the    call */
//
//         {
//
//               report_last_error(m_pLua, true);
//
//               goto failed;
//
//         }
//
//         /* retrieve    results    */
//
//         nres = -nres; /* stack index of    first result */
//
//         while (*sig)
//
//         { /* get results */
//
//               switch (*sig++)
//
//               {
//
//               case 'd': /* double    result */
//
//                         if (!lua_isnumber(m_pLua, nres))
//
//                                 error_msg(true, "wrong    result type,function name: %s\n", func);
//
//                         *va_arg(vl, double*) = lua_tonumber(m_pLua, nres);
//
//                         break;
//
//               case 'f': /* float    result */
//
//                         if (!lua_isnumber(m_pLua, nres))
//
//                                 error_msg(true, "wrong    result type,function name: %s\n", func);
//
//                         *va_arg(vl, float*) = (float)lua_tonumber(m_pLua, nres);
//
//                         break;
//
//               case 'i': /* int result    */
//
//                         if (!lua_isnumber(m_pLua, nres))
//
//                                 error_msg(true, "wrong    result type,function name: %s\n", func);
//
//                         *va_arg(vl, int*) = (int)lua_tonumber(m_pLua, nres);
//
//                         break;
//
//               case 's': /* string    result */
//
//                         if (!lua_isstring(m_pLua, nres))
//
//                                 error_msg(true, "wrong    result type,function name: %s\n", func);
//
//                         *va_arg(vl, std::string*) = lua_tostring(m_pLua, nres);
//
//                         break;
//
//               case 'b': /* boolean argument */
//
//                         if (!lua_isboolean(m_pLua, nres))
//
//                                 error_msg(true, "wrong    result type,function name: %s\n", func);
//
//                         *va_arg(vl, bool*) = (0 != lua_toboolean(m_pLua, nres));
//
//                         break;
//
//               case 'u': /* light user data */
//
//                         if (!lua_isuserdata(m_pLua, nres))
//
//                                 error_msg(true, "wrong    result type,function name: %s\n", func);
//
//                         *va_arg(vl, void**) = lua_touserdata(m_pLua, nres);
//
//                         break;
//
//               default:
//
//                         error_msg(true, "invalid option (%c)\n", *(sig - 1));
//
//               }
//
//               nres++;
//
//         }
//
//
//
//         bIsSuccess = true;
//
// failed:
//
//         va_end(vl);
//
//         //clear the stack
//
//         lua_settop(m_pLua, nSize1);
//
//
//
// #if DEBUG_STACK
//
//         //debug
//
//         int nSize2 = lua_gettop(m_pLua);
//
//         printf("debug lua: stack size after ExecuteScriptFunc = %d\n", nSize2);
//
//         if (nSize1 != nSize2)
//
//               stackDump(m_pLua);
//
// #endif
//
//         return bIsSuccess;
// }

页: [1]
查看完整版本: C++调用LuaJit的Demo