Programming in Lua 3 독서노트(26)

3999 단어
날짜:2014.8.12
PartⅣ The C API 
30 Managing Resources
이전 절에서 이루어진 사용자 정의 유형에 대해 우리는 자원 관리에 관심을 두지 않았다.이전 절에서 실현된 그룹은 메모리 문제에 관심을 가져야 하며, 이러한 문제들은 루아가 관리한다.그러나 일이 쉽지 않을 때가 많다. 일부 대상은 메모리 공간을 필요로 할 뿐만 아니라 창 핸들, 파일 설명 등 자원을 필요로 한다.비록 이것도 메모리 비용이라고 말하지만, 이 자원들은 시스템의 다른 구성 요소에 의해 관리된다.이런 상황에서 대상이 회수되면 우리도 이러한 추가 자원을 회수하는 데 적합한 메커니즘이 필요하다.
17.6장에서 Lua가 제공하는finalizer를 소개한다.gc원 방법으로 구성된 메커니즘이 장에서는 C와 API에서도 리소스 관리를 정상적으로 수행할 수 있도록 Lua에서 두 가지 메커니즘을 확장합니다.첫 번째 예는 하나의 함수가 하나의 디렉터리를 두루 훑어보는 실현이다.두 번째 예는 XML 에셋을 여는 파서인 Expat의 바인딩입니다.
30.1 A Directory Iterator
이전에 이미 유사한dir 함수를 실현했는데, 함수는 주어진 디렉터리에 있는 모든 파일을 포함하는table을 되돌려줍니다.여기서 우리는 매번 호출할 때마다 하나의 교체기를 되돌려주고 하나의 항목을 대표해야 한다. 그러면 우리는 다음과 같은 방식으로 디렉터리를 훑어볼 수 있다.
e.g.
for fname in dir.open(".") do
     print(fname)
end
C에서 디렉토리를 반복하려면 DIR 데이터 구조가 필요합니다.또한 데이터 구조 DIR의 실례는 Opendir에서 만들어야 하며,closedir를 호출할 때 이 실례를 즉시 풀어야 합니다.앞서 설명한 구현dir 함수는 DIR의 실례를 국부 변수로 저장한 다음 마지막 파일 이름을 얻은 후에 이 실례를 방출합니다.그런 다음 DIR 인스턴스는 로컬 변수로 저장할 수 없으며 이 인스턴스에 액세스할 수 있는 액세스가 얼마나 많을지 고려합니다.뿐만 아니라 마지막 파일 이름을 얻을 때만 방출 작업을 할 수 없다. 프로그램이 중간에 순환을 종료하면 더 이상 방출되지 않기 때문이다.따라서 DIR의 실례 주소를 userdataum 형식으로 저장하고 을 사용합니다gc원 방법으로 이userdataum을 관리합니다. 이 자원을 방출하는 데 사용됩니다.
세 가지 C 함수를 빌려 우리의 요구를 실현해야 한다. 하나, dir를 사용해야 한다.open 함수, Lua는 교체기를 만들고, 이 함수는 DIR 구조를 열고, 이 구조를 upvalue 형식의closure를 만듭니다.2, 하나의iterator 함수;3,__gc원 방법으로 자원을 방출합니다.물론 매개 변수의 초기화 작업을 하기 위해 추가 함수도 필요하다.
우선,dir.open 함수.디렉터리를 열기 전에userdatum을 만들어야 합니다. 순서가 바뀌면 메모리 오류가 발생할 수 있기 때문입니다.순서가 정확한 토대 위에서 DIR 구조를 만들자마자userdatum와 연결되었고 이후gc원 방법은 그에 대한 석방 작업을 인수할 것이다.
그리고diriter 함수, 함수는 upvalue에서 DIR 구조의 주소를 얻어서readdir를 호출하여 다음 항목을 읽습니다.
이어서 함수dirgc 대표gc원 방법.이 방법은 디렉터리를 끄지만 주의해야 할 점은 다음과 같습니다. 디렉터리를 열기 전에 userdatum을 만들었기 때문에 Opendidr의 결과가 어떻든 userdatum를 회수합니다.
마지막으로luaopendir 함수, 이 라이브러리를 열 함수입니다.
모두 C 함수 형식으로 이루어졌다.
30.2 An XML Parser
Lua와 Expat의 연결을 간단하게 실현하는 lxp라고 합니다.Expat은 C로 작성된 XML1의 소스입니다.0 파서.이 파서는 SAX(the Simple API for XML)로 구현됩니다.SAX는 API 기반 이벤트 배포기, 즉 SAX 파서에서 XML 문서 한 줄을 읽은 후 리셋을 통해 프로그램이 읽은 정보를 알려줍니다.예를 들어 우리가 Expat를 사용하여 문자열'hi'를 해석하면 세 가지 이벤트가 생성됩니다. 하위 문자열''를 읽으면 start-element 이벤트가 생성됩니다."hi"를 읽을 때text 이벤트 생성하기;""을(를) 읽을 때 endelement 이벤트 이벤트를 생성합니다.모든 이벤트는 프로그램에서 상응하는 리셋 이벤트에 대응합니다.
Expat에는 매우 많은 사건이 있는데, 여기서 주로 위에서 언급한 세 가지 사건을 소개한다.
먼저 Expat 파서를 생성하고 지우는 함수에 대해 설명합니다.
e.g.
XML_Parser XML_ParserCreate(const char *encoding);     /*    */
void XML_ParserFree(XML_Parser p);                              /*    */

첫 번째 함수의 매개 변수인 encoding은 선택할 수 있습니다. 여기는 NULL을 사용합니다.
파서를 받은 후에는 리셋 핸들을 등록해야 합니다.
void XML_SetElementHandler(XML_Parser p,
                                             XML_StartElementHandler start,     /* start    */
                                             XML_EndElementHandler end);      /* end    */
void XML_SetCharacterDataHandler(XML_Parser p, XML_CharacterDataHandler hndl); /* text    */

모든 리셋 핸들은 사용자 데이터를 첫 번째 인자로 받아들인다.그리고 start-element 핸들도 tag의 이름과 tag의 속성을 매개 변수로 받아들인다.
typedef void (*XML_StartElementHandler) (void *uData,const char *name,const char **atts);

end-element 핸들은 tag의 이름에 대한 추가 매개 변수만 수락합니다.
typedef void(*XML_EndElementHandler)(void *uData,const char *name);

text 핸들은 text가 매개 변수로 이 text의 길이를 더하는 것을 받아들인다.
typedef void(*XML_CharacterDataHandler)(void *uData,const char *s,int len);

해석할 정보를 파서에 전달하려면 다음 함수를 사용합니다.
int XML_Parse(XML_Parser p,const char *s,int len,int isLast);

Expat에서 XML 연속 호출Parse - 처리할 문서를 블록으로 수락합니다.마지막 매개변수 isLast는 해석할 때마다 문서의 마지막 블록인지 여부를 나타냅니다.우리는 여기에 모든 블록의 실제 길이를 매개 변수로 사용하기 때문에 모든 블록에 0 종지부 표시를 할 필요가 없다.이 함수는 해석 오류가 발생했을 때 0을 되돌려줍니다.
마지막 함수는 사용자 데이터를 설정하여 각 핸들에 전달하는 것입니다.
void XML_SetUserData(XML_Parser p ,void *uData);

     
전재 대상:https://www.cnblogs.com/zhong-dev/p/4044552.html

좋은 웹페이지 즐겨찾기