번역서 정보 | 번역서 질문&의견 | 번역 이야기 | 문서 창고 | 방명록

루아 모듈의 이름 충돌 방지(2/n)

류광, 2016/04/29 23:02
이번 글에서는 루아 C API를 이용한 루아 C/C++ 확장 모듈의 이름 충돌 방지를 살펴봅니다.

이전 글에서는 순수 루아 모듈의 이름 충돌 방지를 이야기했습니다. 이번 글에서는 루아 C API를 이용한 루아 C/C++ 확장 모듈의 이름 충돌 방지를 살펴봅니다.

C/C++ 확장 모듈의 이름 충돌 문제도 순수 루아 모듈의 것과 본질적으로 동일합니다. 결국은 모듈이 전역 변수(함수도 그냥 함수 형식의 값을 가진 변수임을 기억하세요)를 만드느냐, 다른 말로 하면 전역 테이블을 건드리느냐의 문제입니다.

이전 글의 처음에 등장하는 “원시적인” 함수 라이브러리의 모듈에 해당하는 C/C++ 확장 모듈은 루아 '접착제' 함수들 각각을 lua_register(또는 lua_pushcfunction과 lua_setglobal의 조합)을 이용해서 직접 전역 테이블에 추가하는 형태일 것입니다. 이전 글에서도 말했듯이 이런 접근방식으로는 이름 충돌을 피할 수 없습니다.

개별 함수들의 이름 충돌을 피하기 위해서는 함수들을 하나의 테이블로 묶을 필요가 있는데, 그런 경우를을 위해 루아 5.0과 5.1은 luaL_register라는 보조 함수를 제공합니다. 아마 5.0과 5.1용 C 확장 모듈은 대부분 이 함수를 사용할 것입니다.

void luaL_register (lua_State *L,
                    const char *libname,
                    const luaL_Reg *l);

libname 매개변수에 이름(C 문자열)을 지정해서 이 함수를 호출하면 그 이름으로 전역 변수가 만들어집니다. 예를 들어 PIL 제1판(루아 5.0 대응)과 제2판(루아 5.1 대응) §28.1에는 다음과 같은 예제가 있습니다.

static const struct luaL_Reg arraylib [] = {
  {"new", newarray},
  {"set", setarray},
  {"get", getarray},
  {"size", getsize},
  {NULL, NULL}
};

int luaopen_array (lua_State *L) {
  luaL_register(L, "array", arraylib);
  return 1;
}

이 코드는 new, set, get, size라는 필드(값은 C 함수)를 가진 테이블을 생성해서 array라는 이름의 전역 변수에 배정합니다. 결과적으로, 전역 이름공간 오염의 관점에서는 이전 글의 “require"mymp3lib"” 예제와 같습니다.

다행히 luaL_register의 libname 매개변수에 널(0)을 지정할 수 있습니다. 그러면 luaL_register는 그냥 테이블에 생성하기만 하고 전역 변수에는 배정하지 않습니다. 그 테이블을 그대로 돌려주기만 하면 이전 글의 “local my_movie_lib = require"movie_lib"” 패턴과 같은 효과가 납니다. 지금 예의 경우 luaopen_array를 다음처럼 바꾸면 됩니다.

int luaopen_array (lua_State *L) {
  luaL_register(L, 0, arraylib); // "array" 대신 널 포인터
  return 1;
}

(현대적인 C++에서는 0 대신 nullptr를 사용해야겠죠.)

루아 5.2에서는 luaL_register가 사라지고 luaL_newlib가 생겼습니다. 다음에서 보듯이 모듈 이름을 지정하는 매개변수가 아예 없습니다.

void luaL_newlib (lua_State *L, const luaL_Reg *l);

따라서 일부러 luaL_register를 만들어서 쓰지 않는 한, 5.2부터는 전역 이름공간을 오염시키지 않는 모듈 패턴이 '저절로' 적용됩니다.

이것으로 테이블 안에 담긴 함수 라이브러리 형태의 확장 모듈의 이름공간 오염 문제는 확실히 해결됩니다. 그러나 루아의 이름 충돌 문제가 모두 해결된 것은 아닙니다. 이전 글의 “local video_engine = require"my_video_engine"” 예제처럼 마치 클래스 비슷하게 사용하는 모듈을 C API로 구현하는 경우에는 겉으로 드러나는 전역 이름공간 말고도 오염될 수 있는 이름공간이 더 있기 때문입니다. 이에 대해서는 다음 글에서 살펴보겠습니다.

top
트랙백 0 : 의견 # + 0

"클라우드를 관리하는 기술" 증정 이벤트 결과 발표

류광, 2016/03/10 18:01

*** 아직 제 편지 못 받으신 당첨자 분은 스팸함을 한 번 확인해 보세요. 보낸 사람 이름은 'GpgStudy'입니다('류광'이 아니라).***

세 문제의 답은

  1. Lua(루아)
  2. PHP
  3. Python(파이썬, 파이선)

입니다. 누구나 맞출 수 있게 쉽게 낸다고 냈는데, 2번에서 좀 삐끗했습니다.

세 문제 모두 맞춘 분들의 수가 3을 초과해서, Random.org의 목록 무작위화 서비스(https://www.random.org/lists/)를 이용해서 세 분을 추첨했습니다. 당첨자는 다음과 같습니다.

  1. Geunho Lee
  2. Se-Yeon Kim
  3. 김영호

세 분 축하합니다. 조만간 메일이 갈 것이니 답장해 주시고요.

참여해주신 모든 분께 감사드립니다!

top
트랙백 0 : 의견 # + 0

독자 증정 이벤트 추가 사항입니다.

류광, 2016/03/05 21:26

문제 2가 애매해서 문구를 바꾸었다는 이야기를 원 글의 끝에 추가했는데 혹시 못 보신 분들이 있을까봐 다시 알려 드립니다.

어제(3월 4일) 오후 2시 50분 경에, 문제 2의 마지막 문장에 "(같은 책의 제1판과 제2판)"이라는 문구를 추가했습니다. 원래 문제에서는 제가 생각한 것과는 다른 답이 가능했는데, 이 문구 때문에 이제는 제가 생각한 답만 정답이 됩니다.

어제 오후 3시 30분까지 제출된 답들에 대해서는 다른 답도 정답으로 처리해 드린다고는 했지만, 원래 문제를 보고 답을 찾았다가 나중에야 방명록에 쓰신 분들도 있을 수 있고, 또 실제로 글을 올린 시간과 Disqus(이 곳에서 사용하는 클라우드 댓글 시스템) 쪽에 등록된 시간에 차이가 있을 수도 있어서, 이렇게 하기로 했습니다:

혹시 제출한 답이 아닌 것 같다 싶으신 분들은, 원하시면 언제라도(물론 마감 전까지) 비공개 방명록에 다시 답을 제출하셔도 좋습니다.

마지막으로 제출한 답만 보겠습니다. 기존 글을 수정하면 제가 못 보고 지나칠 수 있으니 새 글로 올려 주세요. 문제 2뿐만 아니라 문제 1이나 3의 답을 새로 제출하는 것도 가능합니다.

진행이 매끄럽지 못한 점 죄송합니다!

top
TAG 공지
트랙백 0 : 의견 # + 0

번역서 "클라우드 시스템을 관리하는 기술" (원제 The Practice of Cloud System Administration) 출간 소식 및 증정 이벤트 공지

류광, 2016/03/04 15:02
The Practice of Cloud System Administration 번역서 "클라우드 시스템을 관리하는 기술"이 저번 주에 나왔습니다. 독자 증정 이벤트도 진행합니다. 이벤트 문제가 조금 바뀌었으니 확인하세요~

본문 열기

top
TAG 번역서
트랙백 0 : 의견 # + 0

Artificial Intelligence: A Modern Approach 3rd 번역서 "인공지능: 현대적 접근방식" 나왔습니다.

류광, 2016/02/11 22:24
Artificial Intelligence: A Modern Approach 3rd 번역서 "인공지능: 현대적 접근방식" 출간 및 증정 이벤트 소식.

본문 열기

top
트랙백 0 : 의견 # + 0

◀ PREV : [1] : [2] : [3] : [4] : [5] : ... [56] : NEXT ▶