블로그는 나의 힘!
[ Programing ]/Lua Scirpt2022. 3. 6. 01:38

앞에 정리에서는 루아 글루 함수를 루아 스크립트에서 호출하고 그 반환값을 활용하는 방법에 관해서
예제로 알아 보았습니다.

이번에는 반대로 루아 스크립트의 함수를 C++에서 호출하고 그 반환값을 활용하는 방법에 관해서 예제를
통해서 알아 보고자 합니다.

 

C++에서 루아 함수를 호출하기 위해서는 
해당 루아 함수가 있는 스크립트 파일이 로드되고 컴파일 과정까지를 마친 상태여야 된다.

그 후 해당 루아 함수에 필요한 인자 값을 넘겨야 하고, 해당 루아 함수를 호출하고 반환값을 받아서 처리 해야 된다.

 


======= 호출 과정 =======

1.  스크립트 파일을 로드하고, 컴파일 하는 과정에 관련된 함수는 앞에서 이미 봤던 함수들이다.

--  스크립트 파일을 로드, 컴파일, 실행
int lua_dofile(lua_State* L, const char* filename);

-- 스크립트 파일을 로드, 커파일 
int lua_loadfile(lua_State* L, const char*filename);

  ※ 실제로 아래 예제에서 lua_loadfile() 함수를 사용해보니 되지가 않던데 그에 관한 이유는 아직 모르겠네요~
     혹시라도 아시는 분 있으시면 설명 부탁 드립니다. ^^*

 

2. 호출할 루아 함수 이름을 스택에 쌓는다.

void lua_getglobal(lua_State* L, const char* name);

 

3. 루아 함수에 필요한 인자 값을 넘겨 줄때는 스택에 해당 인자값들을 push 하면 됩니다.

  -- 해당 인자값의 자료형에 맞게 스택에 push 하면 된다.
  -- 한번에 하나씩 push하고, 스택에 구조에 맞게 push한다.

void lua_pushboolean(lua_State* L, int b);
void lua_pushinterger(lua_State* L, lua_Integer n);
void lua_pushnumber(lua_State* L, lua_Number n);

void lua_pushstring(lua_State* L, const char* s);
void lua_pushlstring(lua_State* L, const char* s);
const char* lua_pushfstring(lua_State* L, const char* fmt, ...);


 


4. 루아 함수에 필요한 인자값들을 모두 스택에 push 했으며, 해당 함수를 호출한다.

  -- lua_getglobal()로 스택에 쌓아놓은 함수를 호출한다.
  -- 스택에 올려 놓은 인자값의 개수와 루아 함수에서 반환할 반환값의 개수를 인자로 한다.

void lua_call(lua_State* L, int narg, int nresults);

 

 

======= C++에서 루아 함수 호출 예제 =======

예제는 "정리 10"에서 사용했던 예제를 수정하였습니다.

 

// 게임의 NPC 이름을 등록하고 삭제하는 프로그램을 루아와 연동하여 처리

// 시스템 헤더 포함
#include <iostream>
#include <list>

using namespace std;

// 루아 헤더 포함
extern "C" {
     #include <lua.h>
     #include <lualib.h>
     #include <lauxlib.h>
}

// NPC Name List
list<const char*> gpNPCName;
int gIndxNPC;

// NPC 이름을 찾아서 지우는 함수
int  _FindDelNPC(const char* pName)
{
     list<const char*>::iterator p = gpNPCName.begin();
     while (p != gpNPCName.end())
     {
          if(0 == stricmp(*p, pName))
          {
               gpNPCName.erase(p);
               return 0; 
          }
          p++;
     }
     return -1;  // 실패시
}

// 리스트에 NPC 이름을 등록
extern "C" int _addNPC(lua_State* pLuaState)
{
     const char* pName = luaL_optstring(pLuaState, 1, 0);
     gpNPCName.push_back(pName);
     //printf("addNPC Name : %s\n",pName);

     lua_pushstring(pLuaState, pName);
     return 0;
}

// NPC 이름을 삭제 함수
extern "C" int _deleteNPC(lua_State* pLuaState)
{
     int  nChkIndx = -1;
     const char* pName = luaL_optstring(pLuaState, 1, 0);
     nChkIndx = _FindDelNPC(pName);

     if(-1 == nChkIndx)
     {
          printf("Can't find Name : %s\n", pName);
          return 0;
     }
     //printf("deleteNPC Name : %s\n", pName);

     lua_pushstring(pLuaState, pName);
     return 0;
}

// 현재 NPC들을 출력 하는 함수
extern "C" int _ViewNPC(lua_State* pLuaState)
{
     int i = 0;
     list<const char*>::iterator p = gpNPCName.begin();
 

     while (p != gpNPCName.end())
     {
          i++;
          //cout << "Now NPC : " << *p << endl;
          lua_pushstring(pLuaState, *p);
          p++;
     
     return i;
}

// 루아글루 함수 등록을 위한 배열
static luaL_reg LuaGlue[] =
{
     {"addNPC",  _addNPC},
     {"deleteNPC", _deleteNPC},
     {"ViewNPC",  _ViewNPC},
     {NULL,   NULL}
};

int main(void)
{
     puts("Lua Console (basic) (c) 2004 Charles River Media");
     puts("Enter Lua commands at the prompt, [QUIT] to exit\n\n");

     // 루아 환경 생성 및 설정
     lua_State *pLuaState = lua_open();
     luaopen_base(pLuaState);
     luaopen_io(pLuaState);
     luaopen_string(pLuaState);
     luaopen_math(pLuaState);
     luaopen_debug(pLuaState);
     luaopen_table(pLuaState);

     // 루아 글루 함수 등록
     for(int i=0; LuaGlue[i].name; i++)
     {
          lua_register(pLuaState, LuaGlue[i].name, LuaGlue[i].func);
     }

     lua_dofile(pLuaState, "D:\\lua_scr\\luaNPC.lua");
     // luaL_loadfile(pLuaState, "D:\\lua_scr\\luaNPC.lua");
     // lua_pcall(pLuaState, 0, LUA_MULTRET, 0);    //! LUA_MULTRET == -1
 
     lua_getglobal(pLuaState, "TestFunc");
     lua_pushnumber(pLuaState, 1);
     lua_call(pLuaState, 1, 1);

     printf("Lua return value : %s\n", (const char*)lua_tostring(pLuaState, -1));

     lua_close(pLuaState);
     return 0;
}

 

 

======= 루아 스크립트 소스 =======

-- New C functions exposed to lua
-- addNPC("NPC Name")
-- deleteNPC("NPC Name")

print("Simple Lua Program!!")
npcName = addNPC("Joe")
print("Add NPC Name : ", npcName)
npcName = addNPC("Sue")
print("Add NPC Name : ", npcName)
npcName = addNPC("Kan")
print("Add NPC Name : ", npcName)
npcName = addNPC("Babo")
print("Add NPC Name : ", npcName)

npcName = deleteNPC("Sue")
print("Dell NPC Name : ", npcName)

npc1, npc2, npc3 = ViewNPC()
print("Now NPC : ", npc1, npc2, npc3)

print("\nLua Func TestFunc\n")

function TestFunc(npcCnt)

     local npc
     if npcCnt == 1 then
          print("First NPC Name\n")
          npc = npc1
     elseif npcCnt == 2 then
          print("Second NPC Name\n")
          npc = npc2
     else
          print("Else NPC Name\n")
          npc = npc3
     end
     return npc
end

※ 소스 설명은 앞의 정리들의 내용과 많이 중복 되는 부분이라서 생략하였습니다.
   혹시라도 궁금한점 있다면 글 남겨 주세요~
  

 

======= 실행 결과 =======

......





[출처] Lua - 11. 루아 스크립트 함수를 C++에서 호출하여 활용|작성자 악마



 

Posted by Mister_Q