보조 라이브러리
보조 라이브러리 (The Auxiliary Library)
보조 라이브러리(auxiliary library)는 C API를 더 편리하고 안전하게 쓰기 위한 함수들의 집합이에요. 이 함수들은 luaL_ 접두사를 쓰며, lauxlib.h 헤더에 선언돼 있어요. 보조 라이브러리는 기본 API인 lua.h(기본 C API) 위에 구축돼 있어서, 상위 수준의 추상화를 제공해요.
보조 라이브러리의 함수들은 네 종류로 나뉘어요.
- 오류 검사/보고 함수: 인자를 검사하고 오류를 내는 데 쓰여요.
- 형식화 출력 함수: 오류 메시지나 로그를 만들 때 쓰여요.
- 파일/문자열 로드 함수: 루아 청크를 읽어 실행하는 데 쓰여요.
- 레지스트리 편의 함수:
luaL_ref/luaL_unref등으로 값을 참조로 보관하는 데 쓰여요.
주요 보조 함수
상태 관리
lua_State *L = luaL_newstate(); // 표준 할당자로 새 상태 생성
luaL_openlibs(L); // 표준 라이브러리를 모두 엶
lua_close(L);
luaL_newstate()— 표준 메모리 할당자를 사용하는 새 루아 상태를 만들어요. 실패하면NULL을 반환해요.luaL_openlibs(L)— 상태L에 루아의 모든 표준 라이브러리(base,string,table,math,io,os,coroutine,utf8,debug등)를 열어요.
문자열 로드와 실행
luaL_dostring(L, s)— 문자열s를 루아 청크로 컴파일하고lua_pcall로 실행해요.luaL_loadstring+lua_pcall의 축약이에요.luaL_dofile(L, filename)— 파일을 로드해 실행.filename이NULL이면 표준 입력을 읽어요.luaL_loadstring(L, s)— 문자열을 청크로 컴파일해 스택에 밀어 올려요.luaL_loadfile(L, filename)— 파일을 청크로 컴파일.luaL_loadbuffer(L, buff, size, name)— 메모리 버퍼를 청크로 로드.
오류 검사 함수
보조 라이브러리의 검사 함수들은 스택 인자의 타입을 검사하고, 잘못되면 오류를 발생시켜요.
luaL_checkinteger(L, idx)— 정수로 검사·반환. 아니면 오류.luaL_checknumber(L, idx)— 숫자로 검사·반환.luaL_checkstring(L, idx)/luaL_checklstring(L, idx, &len)— 문자열 검사·반환 (길이도 함께).luaL_checktype(L, idx, type)— 특정 타입인지 검사.luaL_checkany(L, idx)— 어떤 값이든 존재(비-nil)하는지 검사.luaL_checkoption(L, idx, def, lst)— 옵션 문자열을 목록에서 찾기.luaL_checkstack(L, n, msg)— 스택 공간 확보 검사.luaL_checkudata(L, idx, tname)— 사용자 데이터의 메타테이블이tname인지 검사.luaL_argerror(L, arg, extramsg)— 인자 오류 보고.
옵션 계열:
luaL_optinteger(L, idx, def)— 인자가nil이면 기본값def반환, 아니면 정수로 검사.luaL_optnumber,luaL_optstring,luaL_optlstring,luaL_opt— 동일한 "있으면 검사, 없으면 기본값" 패턴.
오류 보고
luaL_error(L, fmt, ...)— 형식화된 오류 메시지로 루아 오류를 발생시켜요. 위치 정보를 자동으로 추가하고, 함수에서return luaL_error(...)패턴으로 사용돼요.luaL_argerror(L, arg, ...)— 특정 인자에 관한 오류.luaL_typeerror(L, arg, tname)— 타입 불일치 오류.luaL_traceback(L, L2, msg, level)— 오류 메시지에 스택 추적을 덧붙여요.luaL_where(L, level)— 호출 위치 문자열(파일:줄) 생성.luaL_fileresult(L, stat, fname)/luaL_execresult(L, stat)— 파일/실행 결과를 오류 메시지로.
문자열 출력/변환
luaL_addchar,luaL_addstring,luaL_addlstring,luaL_addsize,luaL_addvalue,luaL_buffinit,luaL_prepbuffer,luaL_prepbuffsize,luaL_pushresult,luaL_pushresultsize,luaL_buffaddr,luaL_bufflen,luaL_buffsub,luaL_Buffer— 문자열 버퍼(luaL_Buffer) API를 사용해 여러 문자열을 효율적으로 이어 붙여요.luaL_gsub(L, s, p, r)—s에서 패턴p를r로 모두 치환한 새 문자열 반환.luaL_tolstring(L, idx, &len)— 스택 값의 문자열 표현을 만들어 반환 (숫자, 문자열, 테이블 등).
모듈/라이브러리 등록
luaL_Reg— C 함수 정의 배열 구조체 ({name, func}페어).luaL_setfuncs(L, lr, nup)—luaL_Reg배열의 함수들을 테이블/레지스트리에 등록.luaL_newlib(L, lr)— 새 라이브러리 테이블을 만들고luaL_setfuncs로 채워 스택에 밀어 올림.luaL_newlibtable(L, lr)— 라이브러리 테이블만 생성(함수는 아직 등록 안 함).luaL_register— (5.2에서 제거/변경) 대신luaL_newlib를 사용.luaL_requiref(L, modname, openf, glb)— 모듈을 로드(require처럼)하고, 필요하면openf로 연 뒤 전역에 등록.
메타테이블/사용자 데이터
luaL_newmetatable(L, tname)—tname명의 유일한 메타테이블을 만들어 레지스트리에 저장하고 스택에 밀어 올림 (이미 있으면 기존 것 반환).luaL_setmetatable(L, tname)— 스택 맨 위 값에tname메타테이블 설정.luaL_getmetatable(L, tname)— 레지스트리에서 메타테이블을 스택에 밀어 올림.luaL_getmetafield(L, obj, event)— 객체의 메타테이블에서 필드를 찾아 스택에 밀어 올림.luaL_getsubtable(L, idx, fname)— 테이블 필드가 테이블이면 반환, 아니면 새 테이블 만들어 저장.luaL_testudata(L, ud, tname)— userdata가tname메타테이블을 갖는지 검사 (실패 시 NULL).luaL_checkudata(L, ud, tname)— 동일하되 실패하면 오류.luaL_callmeta(L, obj, e)— 객체에 메타필드e가 있으면 그 함수를obj인자로 호출.luaL_len(L, idx)— 길이 연산자 호출 결과 반환.luaL_Stream— 파일 스트림 userdata를 나타내는 타입.
참조 (References)
luaL_ref(L, t)— 스택 맨 위 값을 테이블t(보통 레지스트리)에 정수 참조로 저장하고 그 정수(1 이상)를 반환해요.luaL_unref(L, t, ref)— 참조를 해제해요.ref가LUA_NOREF나LUA_REFNIL이면 아무것도 하지 않아요.
기타
luaL_typename(L, idx)— 값의 타입 이름 문자열 반환.luaL_typeerror(L, arg, tname)— 예상 타입과 다른 인자에 대한 표준 오류.luaL_argcheck(L, cond, arg, extramsg)— 조건 검사, 거짓이면 인자 오류.luaL_argexpected(L, cond, arg, tname)— 조건 검사 (예상 타입 오류 메시지).luaL_checkversion(L)— 루아 라이브러리 버전 호환성 검사.luaL_version— 관련 버전 상수/함수.luaL_pushfail(L)—nil(또는 오류 표시 값)을 스택에 밀어 올림.luaL_pushresult(L)— 버퍼 내용을 스택에 스트링으로.luaL_pushresultsize(L, sz)— 버퍼의 일부를 스택에.
본문
luaL_Buffer와 문자열 버퍼
luaL_Buffer는 여러 번의 문자열 연결을 반복할 때 임시 메모리 할당을 줄이기 위한 버퍼 구조체예요. luaL_buffinit(L, &b)로 초기화하고, luaL_addstring(&b, s)처럼 조각을 추가한 뒤 luaL_pushresult(&b)로 결과 문자열을 스택에 밀어 올려요. 이 기법은 루아에서 ..를 반복 연결하는 것보다 훨씬 효율적이에요.
모듈 패턴의 예
static const luaL_Reg mylib[] = {
{"add", my_add},
{"sub", my_sub},
{NULL, NULL} // 끝 표시
};
int luaopen_mylib(lua_State *L) {
luaL_newlib(L, mylib);
return 1;
}
이렇게 하면 루아에서 require("mylib")로 모듈을 불러 mylib.add(...)처럼 쓸 수 있어요.