Lua
루아 C API 소개
수색…
통사론
- lua_State * L = lua_open (); // 새 VM 상태를 만듭니다. 루아 5.0
- lua_State * L = luaL_newstate (); // 새 VM 상태를 만듭니다. 루아 5.1 이상
- int luaL_dofile (lua_State * L, const char * filename ); // 지정된 lua_State를 사용하여 주어진 파일 이름 으로 lua 스크립트를 실행한다.
- void luaL_openlibs (lua_State * L); // 모든 표준 라이브러리를 지정된 lua_State에로드합니다.
- void lua_close (lua_State * L); // VM 상태를 닫고 내부의 모든 리소스를 해제합니다.
- void lua_call (lua_State * L, int nargs, int nresults); // 인덱스에서 루아 발론 호출 - (nargs + 1)
비고
루아는 가상 시스템에 적절한 C API를 제공합니다. VM 자체와 달리 C API 인터페이스는 스택 기반입니다. 따라서 데이터와 함께 사용하려는 대부분의 기능은 가상 스택의 일부를 추가하거나 제거하는 것입니다. 또한 모든 API 호출은 스택 내에서 신중하게 사용해야하며 한계가 있습니다.
일반적으로 Lua 언어에서 사용할 수있는 것은 C API를 사용하여 수행 할 수 있습니다. 또한 내부 레지스트리에 대한 직접 액세스, 표준 메모리 할당 자 또는 가비지 수집기의 변경 동작과 같은 몇 가지 추가 기능이 있습니다.
터미널에서 다음을 실행하여 제공된 Lua C API 예제를 컴파일 할 수있다.
$ gcc -Wall ./example.c -llua -ldl -lm
루아 가상 머신 만들기
#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>
int main(void)
{
/* Start by creating a new VM state */
lua_State *L = luaL_newstate();
/* Load standard Lua libraries: */
luaL_openlibs(L);
/* For older version of Lua use lua_open instead */
lua_State *L = lua_open();
/* Load standard libraries*/
luaopen_base(L);
luaopen_io(L);
luaopen_math(L);
luaopen_string(L);
luaopen_table(L);
/* do stuff with Lua VM. In this case just load and execute a file: */
luaL_dofile(L, "some_input_file.lua");
/* done? Close it then and exit. */
lua_close(L);
return EXIT_SUCCESS;
}
루아 함수 호출하기
#include <stdlib.h>
#include <lauxlib.h>
#include <lua.h>
#include <lualib.h>
int main(void)
{
lua_State *lvm_hnd = lua_open();
luaL_openlibs(lvm_hnd);
/* Load a standard Lua function from global table: */
lua_getglobal(lvm_hnd, "print");
/* Push an argument onto Lua C API stack: */
lua_pushstring(lvm_hnd, "Hello C API!");
/* Call Lua function with 1 argument and 0 results: */
lua_call(lvm_hnd, 1, 0);
lua_close(lvm_hnd);
return EXIT_SUCCESS;
}
위의 예제에서 우리는 다음과 같은 작업을 수행합니다.
- 첫 번째 예제와 같이 Lua VM을 생성하고 설정한다.
- 전역 루아 테이블에서 가상 스택으로 루아 함수를 가져 와서 푸시
- 문자열
"Hello C API"
를 입력 인수로 가상 스택에 푸시 - VM에 이미 스택에있는 하나의 인수가있는 함수를 호출하도록 VM에 지시
- 폐쇄 및 청소
노트:
염두에두고, lua_call()
은 함수를 lua_call()
스택의 결과를 남기는 인수입니다.
또한 루아 보호 호출 - lua_pcall()
사용하는 것이 더 안전합니다.
맞춤 API 및 루아 사용자 정의가 포함 된 임베디드 루아 통역사
루아 인터프리터를 C 코드에 임베드하고, C 정의 함수를 Lua 스크립트에 노출시키고, Lua 스크립트를 평가하고, 루아에서 C 정의 함수를 호출하고, C (호스트)에서 루아 정의 함수를 호출하는 방법을 보여줍니다.
이 예제에서는 Lua 스크립트로 분위기를 설정하고자합니다. 여기 분위기가있어 .lua :
-- Get version information from host
major, minor, build = hostgetversion()
print( "The host version is ", major, minor, build)
print("The Lua interpreter version is ", _VERSION)
-- Define a function for host to call
function mood( b )
-- return a mood conditional on parameter
if (b and major > 0) then
return 'mood-happy'
elseif (major == 0) then
return 'mood-confused'
else
return 'mood-sad'
end
end
스크립트에서 mood()
가 호출되지 않았다는 것을주의하십시오. 호스트 응용 프로그램이 호출하도록 정의 된 것입니다. 또한 스크립트가 스크립트에 정의되지 않은 hostgetversion()
이라는 함수를 호출 함을 hostgetversion()
하십시오.
다음으로 'mood.lua'를 사용하는 호스트 응용 프로그램을 정의합니다. 다음은 'hostlua.c'입니다.
#include <stdio.h>
#include <lua.h>
#include <lualib.h>
#include <lauxlib.h>
/*
* define a function that returns version information to lua scripts
*/
static int hostgetversion(lua_State *l)
{
/* Push the return values */
lua_pushnumber(l, 0);
lua_pushnumber(l, 99);
lua_pushnumber(l, 32);
/* Return the count of return values */
return 3;
}
int main (void)
{
lua_State *l = luaL_newstate();
luaL_openlibs(l);
/* register host API for script */
lua_register(l, "hostgetversion", hostgetversion);
/* load script */
luaL_dofile(l, "mood.lua");
/* call mood() provided by script */
lua_getglobal(l, "mood");
lua_pushboolean(l, 1);
lua_call(l, 1, 1);
/* print the mood */
printf("The mood is %s\n", lua_tostring(l, -1));
lua_pop(l, 1);
lua_close(l);
return 0;
}
출력은 다음과 같습니다.
The host version is 0 99 32
Lua interpreter version is Lua 5.2
The mood is mood-confused
'hostlua.c'를 컴파일 한 후에도 'mood.lua'를 수정하여 프로그램의 출력을 자유롭게 변경할 수 있습니다!
표 조작
테이블의 인덱스를 액세스하거나 변경하려면 테이블을 스택에 배치해야합니다.
이 예제에서는 테이블이 tbl이라는 전역 변수라고 가정 해 봅시다.
특정 색인에서 콘텐츠 가져 오기 :
int getkey_index(lua_State *L)
{
lua_getglobal(L, "tbl"); // this put the table in the stack
lua_pushstring(L, "index"); // push the key to access
lua_gettable(L, -2); // retrieve the corresponding value; eg. tbl["index"]
return 1; // return value to caller
}
지금까지 보았 듯이, 테이블을 스택에 넣고 인덱스를 누르고 lua_gettable을 호출하면된다. -2 인수는 테이블이 스택 맨 위에서 두 번째 요소임을 의미합니다.
lua_gettable은 메타 메소드를 트리거합니다. 메타 메소드를 트리거하지 않으려면 대신 lua_rawget을 사용하십시오. 동일한 인수를 사용합니다.
특정 색인에서 콘텐츠 설정 :
int setkey_index(lua_State *L)
{
// setup the stack
lua_getglobal(L, "tbl");
lua_pushstring(L, "index");
lua_pushstring(L, "value");
// finally assign the value to table; eg. tbl.index = "value"
lua_settable(L, -3);
return 0;
}
내용을 얻는 것과 같은 훈련. 스택을 밀고 인덱스를 누른 다음 스택에 값을 밀어 넣어야합니다. 그 후에, 당신은 lua_settable을 호출한다. -3 인수는 스택에있는 테이블의 위치입니다. 메타 메소드를 트리거하지 않으려면 lua_settable 대신 lua_rawset을 사용하십시오. 동일한 인수를 사용합니다.
표에서 다른 곳으로 콘텐츠 전송 :
int copy_tableindex(lua_State *L)
{
lua_getglobal(L, "tbl1"); // (tbl1)
lua_getglobal(L, "tbl2");// (tbl1)(tbl2)
lua_pushstring(L, "index1");// (tbl1)(tbl2)("index1")
lua_gettable(L, -3);// (tbl1)(tbl2)(tbl1.index1)
lua_pushstring(L, "index2");// (tbl1)(tbl2)(tbl1.index1)("index2")
lua_pushvalue(L, -2); // (tbl1)(tbl2)(tbl1.index1)("index2")(tbl1.index1)
lua_settable(L, -4);// (tbl1)(tbl2)(tbl1.index1)
lua_pop(L, 1);
return 0;
}
이제 우리는 여기서 배운 모든 것을 모으고 있습니다. 주석에 스택 내용을 넣어서 분실하지 않도록하십시오.
두 테이블을 스택에 넣고 테이블 1의 인덱스를 스택에 넣고 tbl1.index1
값을 tbl1.index1
. gettable의 -3
인수에 유의하십시오. 나는 두 번째가 아니라 첫 번째 테이블 (위에서 세 번째)을보고있다. 그런 다음 두 번째 테이블의 인덱스를 밀고 tbl1.index1
을 스택 맨 위로 복사 한 다음 위로부터 네 번째 항목에 대해 lua_settable
을 호출합니다.
집안일을 위해서 최상위 요소를 제거 했으므로 두 테이블 만 스택에 남아 있습니다.