English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

Lua 모듈 및 패키지

모듈은 Lua에서부터는 모듈과 유사한 구조를 가지고 있으며, 따라서 모듈을 생성하는 것은 table을 생성하고 필요한 상수, 함수를 넣고 마지막으로 이 table을 반환하는 것으로 간단합니다. 5.1 최초로 Lua는 표준 모듈 관리 기제를 도입하여, 일부 공용 코드를 파일에 넣고 API 인터페이스를 통해 다른 곳에서 호출할 수 있게 하여 코드의 재사용성을 높이고 코드 결합도를 낮추는 데 도움이 됩니다.

Lua는 표준 모듈 관리 기제를 도입하여, 일부 공용 코드를 파일에 넣고 API 인터페이스를 통해 다른 곳에서 호출할 수 있게 하여 코드의 재사용성을 높이고 코드 결합도를 낮추는 데 도움이 됩니다.

-- 파일 이름은 module.lua
-- module이라는 모듈 정의
module = {}
 
-- 상수 정의
module.constant = "이는 상수입니다"
 
-- 함수 정의
function module.func1())
    io.write("이는 공개 함수입니다!\n")
end
 
local function func2())
    print("이는 개별 함수입니다!")
end
 
function module.func3())
    func2())
end
 
return module

위와 같이 모듈의 구조는 table의 구조이므로 table 내의 요소를操作하는 것처럼 모듈 내의 상수나 함수를 호출할 수 있습니다.

위의 func2 프로그램 블록의 전역 변수로 선언된 경우, 이는 개별 함수를 의미하며, 따라서 외부에서는 모듈 내의 이 개별 함수에 접근할 수 없습니다. 반드시 모듈 내의 공개 함수를 통해 호출해야 합니다.

require 함수

Lua는 require라는 함수를 제공하여 모듈을 로드합니다. 모듈을 로드하려면 간단히 호출만 해야 합니다. 예를 들어:

require("<모듈명>")

또는

require "<모듈명>"

require 실행 후 모듈 상수나 함수로 구성된 table이 반환되며, 이 table을 포함하는 전역 변수도 정의됩니다.

test_module.lua 파일

-- test_module.lua 파일
-- module 모듈은 위에서 언급된 module.lua
require("module")
 
print(module.constant)
 
module.func3())

위 코드의 실행 결과는 다음과 같습니다:

이는 상수입니다
이는 프라이빗 함수입니다!

또는 로드된 모듈에 별명 변수를 정의하여 호출하기 편리하게 합니다:

test_module2.lua 파일

-- test_module2.lua 파일
-- module 모듈은 위에서 언급된 module.lua
-- 별명 변수 m
local m = require("module")
 
print(m.constant)
 
m.func3())

위 코드의 실행 결과는 다음과 같습니다:

이는 상수입니다
이는 프라이빗 함수입니다!

로드 메커니즘

사용자 정의 모듈에 대해서는, 모듈 파일이 어떤 파일 디렉토리에 위치해도 상관 없습니다. 함수 require는 자신의 파일 경로 로드 전략을 가지고 있으며, Lua 파일이나 C 프로그램 라이브러리에서 모듈을 로드하려고 시도합니다。

require는 Lua 파일의 경로를 전역 변수 package.path에 저장합니다. Lua가 시작되면, 환경 변수 LUA_PATH의 값으로 이를 초기화합니다. 이 환경 변수를 찾지 못하면, 컴파일 시 정의된 기본 경로를 사용하여 초기화합니다。

물론, LUA_PATH 이 환경 변수가 없다면도自定义 설정할 수 있습니다. 현재 사용자 루트 디렉토리에서 .profile 파일을 엽니다(없다면 생성하고 열면 됩니다. .bashrc 파일을 열어도 됩니다),예를 들어 "~/lua/" 경로를 LUA_PATH 환경 변수에 추가합니다:

#LUA_PATH
export LUA_PATH="~/lua/?.lua;;"

파일 경로는 ";"로 구분되며, 마지막 2 개 ";;"는 새로 추가된 경로 뒤에 기본 경로를 추가하는 것을 의미합니다。

그런 다음, 환경 변수 매개변수를 업데이트하여 즉시生效합니다。

source ~/.profile

이 때 package.path의 값은 다음과 같습니다:

/Users/dengjoe/lua/?.lua;./?.lua;/usr/local/share/lua/5.1/?.lua;/usr/local/share/lua/5.1/?/init.lua;/usr/local/lib/lua/5.1/?.lua;/usr/local/lib/lua/5.1/?/init.lua

그래서 require("module")를 호출할 때는 다음 파일 디렉토리를 열어 목표를 검색하려고 시도합니다.

/Users/dengjoe/lua/module.lua;
./module.lua
/usr/local/share/lua/5.1/module.lua
/usr/local/share/lua/5.1/module/init.lua
/usr/local/lib/lua/5.1/module.lua
/usr/local/lib/lua/5.1/module/init.lua

목표 파일을 찾았다면 package.loadfile을 호출하여 모듈을 로드합니다. 그렇지 않으면 C 프로그램 라이브러리를 찾습니다.

검색할 파일 경로는 전역 변수 package.cpath에서 가져옵니다.而这个变量则是通过环境变量 LUA_CPATH 来初始。

검색 전략은 위와 같지만, 지금은 so 또는 dll 유형의 파일을 검색합니다. 찾을 수 있다면, require는 package.loadlib을 통해 그를 로드합니다.

C 패키지

Lua와 C는 쉽게 결합할 수 있습니다. C로 Lua 패키지를 작성합니다.

Lua에서 패키지를 작성하는 것과 달리, C 패키지는 사용하기 전에 먼저 로드하고 연결해야 합니다. 대부분의 시스템에서 가장 쉬운 구현 방법은 동적 연결 라이브러리 메커니즘을 통해 이루어집니다.

Lua는 loadlib 함수 내에 모든 동적 연결 기능을 제공합니다. 이 함수는 두 가지 매개변수를 가집니다: 라이브러리의 절대 경로와 초기화 함수. 따라서 표준 호출 예제는 다음과 같습니다:

local path = "/usr/local/lua/lib/libluasocket.so"
local f = loadlib(path, "luaopen_socket")

loadlib 함수는 지정된 라이브러리를 로드하고 Lua에 연결하지만, 라이브러리를 열지 않습니다(즉, 초기화 함수를 호출하지 않습니다). 그 대신 초기화 함수를 Lua의 함수로 반환하여 Lua에서 직접 호출할 수 있습니다.

로드빌리티 라이브러리를 로드하거나 초기화 함수를 찾을 때 오류가 발생하면 loadlib은 nil과 오류 메시지를 반환합니다. 이전 코드를 수정하여 오류를 검출하고 초기화 함수를 호출할 수 있습니다:

local path = "/usr/local/lua/lib/libluasocket.so"
-- 또는 path = "C:\\windows\\luasocket.dll",이것은 Window 플랫폼에서
local f = assert(loadlib(path, "luaopen_socket"))
f()  -- 실제 라이브러리 열기

보통은 이진 배포 라이브러리가 이전 코드 섹션과 유사한 stub 파일을 포함해야 합니다. 이진 라이브러리를 설치할 때는 어느 디렉토리에나 두고 stub 파일의 실제 이진 라이브러리 경로만 수정하면 됩니다.

stub 파일이 있는 디렉토리를 LUA_PATH에 추가하세요. 이렇게 설정하면 require 함수를 사용하여 C 라이브러리를 로드할 수 있습니다.