Search

"mlx.h"

Created
2021/04/09
tag
C
cub3d
miniRT
miniLibX
mlx.h

Subjects

작성된 글은 42cub3d, miniRT와 같은 Graphics 과제에서 사용되는 "mlx.h"라는 라이브러리에 대해서 다룬다. 라이브러리가 지원하는 함수들과 그 특성에 대해서 알아볼 것이고, 대부분의 내용은 매뉴얼 파일에서 가져왔기 때문에 매뉴얼 파일을 읽는 것이 편하다면 이를 더 권장한다. 각 함수에 대해서 알아본 뒤에는 예제를 통해 함수들을 이용하는 방법을 간단히 소개할 예정이다.

1. mlx

1) 개념

"mlx.h"MiniLibX라고 하여, Unix 계열의 X-Window(X11)에 대한 지식과 Mac OS XAppKit의 지식이 없어도 쉽게 그래픽 관련 소프트웨어를 만들 수 있도록 42 학생들에게 제공되는 라이브러리이다. "mlx.h"include 함으로써 간단한 Window 생성, 그리기 도구, ImageEvent에 대한 관리를 이용할 수 있다. "mlx.h"에서 제공하는 기능들은 내부적으로 Mac OS XOpenGLAppKit을 이용한다. 따라서 "mlx.h"를 이용하여 프로그램을 생성할 땐, OpenGLAppKit을 프레임워크로써 이용하겠다고 명시하여 라이브러리와 Link 해야한다.
X-Window (X11) X-Window는 흔히 X11이라고 부르기도 한다. X-WindowUnix 계열의 운영체제에서 사용하는 Window 시스템 및 Window에 대한 GUI 환경이다. X-Window는 디스플레이 장치에 Window를 표시하며, 마우스 및 키보드와 같은 입력 장치와 상호작용을 하는 등 GUI 환경 구현을 위한 기본 프레임워크를 제공한다. X-WindowMicrosoftWindows에서의 GUI 시스템과는 달리 네트워크 프로토콜에 기반한 GUI 시스템이다. Client-Server Model을 기반으로 하기 때문에 ClientServer간의 네트워크 연결이 요구된다. 서로 네트워크 연결이 되었다면, Client에게 요청을 받았을 때 Server에서 요청을 처리하는 식으로 GUI를 조작하기 때문에 디스플레이 장치에 독립적인 성격을 갖는다. 이는 곧 인터페이스의 모습에 관여하지 않는 것을 의미하므로 X-Window를 사용하는 사용자들의 환경이 매우 다양할 수 있다는 것을 암시한다. 위의 Client-Server Model에 대해서 간단한 상황을 들어보면, 마우스 포인터를 여기로 움직여라 라고 Client가 요청을 보내면 X-WindowServer가 요청을 받아 이를 처리하여 디스플레이 장치에 출력해주는 식이 되겠다. 여기서의 Server는 일반적으로 Client의 머신에서 동작하게 되며, 머신의 System Boot File에 의해서 구동된다.
AppKit AppKitApplication Kit의 줄임말로써 GUI를 위한 프레임워크이다. NeXTSTEP에 의해서 만들어졌으며, NeXTSTEP은 1996년에 Apple에 인수되었다. AppKitFoundation이라는 프레임워크와 함께 상속되어 Cocoa라는 프레임워크를 만드는데 이용되었으며, AppKit의 주요 기능이 Cocoa의 주요 기능 중 하나라고 볼 수 있다. (Apple에서 만든 Cocoa는 객체지향을 따르는 API로, Mac OS X 상의 응용 프로그램을 만드는데 주로 이용되는 프레임워크이다.) AppKitGUI를 위한 프레임워크인 만큼, 인터페이스를 구성하는데 필요한 Window, Button, Scroll Bar, Font, Color와 같은 모든 그래픽적 요소들을 문서 관리의 기본 구조와 함께 클래스로 제공한다. AppKit은 기본적으로 OpenGL을 지원한다. 놀랍게도 AppKit에서 지원하는 기능들 중에는 Grammar Correction, Dragging, Copy, Cut, Paste 등의 기능들도 있다. 이외에도 많은 기능들을 쉽고 편하게 이용할 수 있도록 Apple의 개발자들이 구현해두었다. AppKit을 이용하여 만든 Software는 하나의 Screen에서 다른 Software 혹은 Event System과 함께 표현될 수 있도록 Mac OS XWindow Server와 직접적으로 상호작용할 뿐만 아니라, Software 내부에서 Render 되어야하는 것들을 관리할 수 있도록 Mac OS X에 연결된 GPU와 직접적으로 상호작용하게 된다.

2)mlx_init

함수 원형

void *mlx_init();
C
복사

함수 인자

인자를 받지 않는다.

반환 값

디스플레이 장치와의 연결에 대한 식별자를 void * 타입의 포인터로 반환 (반환된 포인터는 라이브러리 내부의 다른 함수들을 호출할 때 사용된다. 디스플레이 장치와의 연결에 실패하게 되면 NULL을 반환한다.)

참고

"mlx.h"를 통해 그래픽 요소들을 이용하기 위해선 현재 Software와 디스플레이 장치를 연결해줘야 한다. 그렇지 않고선 제공되는 함수들을 이용할 수 없다. mlx_initSoftware와 디스플레이 장치에 대한 연결을 생성해주는 역할을 수행하게 된다. 식별자를 지칭하는 mlx_init의 반환 값은 mlx_ptr로 이용되며, Screen Connection Identifier라고 불린다.

2. mlx_new_window

mlx_new_window 관련 함수들은 Window에 대한 제어를 수행하는데 사용된다.

1) mlx_new_window

함수 원형

void *mlx_new_window(void *mlx_ptr, int size_x, int size_y, char *title);
C
복사

함수 인자

size_xWindowWidth를, size_yWindowHeight를 의미한다. title로 주어지는 문자열은 Window의 제목으로 나타난다. mlx_ptrmlx_init 함수로부터 반환 받은 Screen Connection Identifier이며, mlx_ptr로 지칭되는 연결에 해당하는 Window를 만들기 위해 이용된다.

반환 값

Window에 대한 식별자를 void * 타입의 포인터로 반환 (반환된 포인터는 mlx_init의 반환 값과 마찬가지로 라이브러리 내부의 다른 함수들을 호출할 때 사용된다. Window 생성에 실패하게 되면 NULL을 반환한다.)

참고

MiniLibX는 하나의 Window만 처리할 수 있는 것이 아니라 임의의 여러 Window를 처리할 수 있다. mlx_new_window의 반환 값은 win_ptr로 이용되며, Window Identifier라고 불린다.

2) mlx_clear_window

함수 원형

int mlx_clear_window(void *mlx_ptr, void *win_ptr);
C
복사

함수 인자

Screen Connection Identifier를 의미하는 mlx_ptr, Window Identifier를 의미하는 win_ptr을 인자로 받는다.

반환 값

함수의 원형에서는 int 타입의 반환 값을 갖는다고 하지만, 매뉴얼에 따르면 아무것도 반환하지 않는다고 한다. SwiftForwarding되고 있는 Interface를 직접 확인해보면 아래 코드와 같이 아무런 반환 값이 없는 것을 확인할 수 있다.
@_cdecl("mlx_clear_window") public func mlx_clear_window_swift(_ mlxptr:UnsafeRawPointer, _ winptr:UnsafeRawPointer) { let win:MlxWin = _mlx_bridge(ptr:winptr) win.clearWin() }
Swift
복사

참고

mlx_clear_window 함수는 Window를 검은색으로 초기화하는 함수이다.

3) mlx_destroy_window

함수 원형

int mlx_destory_window(void *mlx_ptr, void *win_ptr);
C
복사

함수 인자

Screen Connection Identifier를 의미하는 mlx_ptr, Window Identifier를 의미하는 win_ptr을 인자로 받는다.

반환 값

함수의 원형에서는 int 타입의 반환 값을 갖는다고 하지만, 매뉴얼에 따르면 아무것도 반환하지 않는다고 한다. SwiftForwarding되고 있는 Interface를 직접 확인해보면 아래 코드와 같이 단순히 0을 반환하는 것을 확인할 수 있다.
@_cdecl("mlx_destroy_window") public func mlx_destroy_window_swift(_ mlxptr:UnsafeRawPointer, _ winptr:UnsafeRawPointer) -> Int32 { let mlx:MlxMain = _mlx_bridge(ptr:mlxptr) /// bridge_transfer to get the retain, at end of this func should release the MlxWin object, because no ref anymore. let win:MlxWin = _mlx_bridge_transfer(ptr:winptr) win.delNotifs() win.flushImages() win.waitForGPU() win.destroyWinE() mlx.winList.removeAll(where: { $0 === win} ) return Int32(0) }
Swift
복사

참고

mlx_destroy_window 함수는 Window를 소멸시키는 함수이다.

3. mlx_new_image

mlx_new_image 관련 함수들은 Image를 조작하는데 사용된다.
Image File Format Image File FormatImage를 디지털로 구성하고 저장하는 표준화된 방법을 의미하는데, 이 형식에 따라서 실제 데이터를 압축되지 않은 형식, 압축된 형식, 벡터 형식 등으로 저장할 수 있다. 형식에 맞게 갖춰진 Image 파일은 컴퓨터 디스플레이 혹은 프린터에서 파일 내의 데이터를 Rastering하여 사용하게 된다. Rastering을 하는 것을 Rasterization이라 하는데, 이는 Image의 데이터를 Pixel Grid로 변환하는 것을 의미한다. 각 Pixel은 색상을 지정할 수 있도록 여러 비트들을 갖고 있는데, 특정 장치에서 Rasterization을 하게 되면 장치 내의 bits_per_pixel을 읽어 Pixel을 올바르게 처리하게 된다.
PNG (Portable Network Graphics) PNG비손실 Image File Format 중 하나이다. GIF라는 Image File FormatLZW라는 데이터 압축 알고리즘을 이용하는데, 이를 소프트웨어 특허로 등록하면서 새롭게 고안된 것이 PNG이다. 이 때 PNGGIF가 갖고 있는 여러 문제를 개선하는 방향으로 만들어졌다. 인터넷 상의 자료들을 나타내기 위해 개발되어 C (Cyan), M (Magenta), Y (Yellow), K (Black)를 지원하지 않는다. GIF PNG 압축률이 상대적으로 낮음 압축률이 상대적으로 높음 단일 투명도 옵션 다양한 투명도 옵션 256가지 색을 지원 Truecolor라는16777216가지 색을 지원 애니메이션을 제공함 애니메이션을 제공하지 않음 JPEG PNG 파일의 크기가 상대적으로 작음 파일의 크기가 상대적으로 큼 손실 Image File Format 비손실 Image File Format 뭉개짐이 나타날 수 있음 뭉개짐이 나타나지 않음
XPM (X Pix Map) X11 상에서 사용되는 Image File Format을 의미한다. XPM 파일은 .XPM의 확장자를 가지며, .XBM 파일을 확장하도록 설계되었다. XPM 파일 내부의 데이터는 C 언어의 정적 문자 배열로 되어 있거나 Plain Text로 되어 있다. XPMXPM, XPM2, XPM3로 나뉘는데, 주어진 3개의 XPMXPM2C 언어 형식을 이용하지 않고 Plain Text로 이용된다. 내부의 데이터가 C 언어의 정적 문자 배열로 되어 있는 경우에는 .XPM.XBM 모두 C 언어로 이뤄진 코드에 포함될 수 있다. 이에 따라 응용 프로그램에 직접 컴파일이 되는 것이 가능하다. XPM의 형식은 아래와 같이 6개의 영역으로 분류된다.
/* XPM Format on C */ static char* <variable_name>[] = { <Values> <Colors> <Pixels> <Extensions> }; /* XPM */ static char * XFACE[] = { /* <Values> */ /* <width/columns> <height/rows> <colors> <chars per pixel>*/ "48 4 2 1", /* <Colors> */ /* <c/color> <m/monochrome> <g/grayscale> <s/symbolic> */ "a c #ffffff", // none indicates transparency "b c #000000", // none indicates transparency /* <Pixels> */ "abaabaababaaabaabababaabaabaababaabaaababaabaaab", "abaabaababaaabaabababaabaabaababaabaaababaabaaab", "abaabaababaaabaabababaabaabaababaabaaababaabaaab", "abaabaababaaabaabababaabaabaababaabaaababaabaaab" };
C
복사

1) mlx_new_image

함수 원형

void *mlx_new_image(void *mlx_ptr, int width, int height);
C
복사

함수 인자

Image의 각 WidthHeight에 해당하는 widthheight를 인자로 받는다. 이렇게 생성된 Image는 메모리 상에 존재하기 때문에 어느 Screen Connection에 해당하는 Image인지 알기 위해서, 생성된 ImageScreen Connection에 기록해둬야 한다. 따라서 Screen Connection Identifiermlx_ptr을 인자로 받는다. (SwiftForwarding된 코드를 확인해보면 mlx_ptr을 이용하여 Image를 기록해두는 것을 알수 있다.)
@_cdecl("mlx_new_image") public func mlx_new_image(_ mlxptr:UnsafeRawPointer, _ width:Int32, _ height:Int32) -> UnsafeRawPointer { let mlx:MlxMain = _mlx_bridge(ptr:mlxptr) let img = MlxImg(d:mlx.device, w:Int(width), h:Int(height)) mlx.addImgToList(img) /// print(CFGetRetainCount(img)) return (_mlx_bridge_retained(obj:img)) }
C
복사

반환 값

Image 에 대한 식별자를 void * 타입의 포인터로 반환 (반환된 포인터는 라이브러리 내부의 Image 관련 함수들을 호출할 때 사용된다. Image 생성에 실패하게 되면 NULL을 반환한다.)

참고

mlx_new_image의 반환 값은 img_ptr로 이용되며, Image Identifier라고 불린다. 디스플레이 장치에 맞는 정보들을 이용하여 Image를 생성한다.

2) mlx_get_data_addr

함수 원형

char *mlx_get_data_addr(void *img_ptr, int *bits_per_pixel, int *size_line, int *endian);
C
복사

함수 인자

Image Identifierimg_ptr을 이용하여 메모리 상에 존재하는 Image에 대해 접근할 수 있도록 해준다. 이어진 3개의 인자 bits_per_pixel, size_line, endian은 포인터로 넘겨 받았기 때문에, 역참조 한 후 그 값을 수정하면 mlx_get_data_addr을 호출한 곳에서도 이 정보를 그대로 활용할 수 있다. bits_per_pixel에는 하나의 Pixel에 색상을 나타내기 위해 몇 비트가 필요한지 채워진다. (이를 Depth of the Image라고도 부른다.) size_line에는 메모리 상에서 Image의 한 행을 표현하는데 사용된 바이트 값이 채워진다. (이 값은 Offset으로 Image의 다른 행을 접근할 때 계산 값으로 사용된다.) endianImage 상의 Pixel에 색상 값이 Little Endian으로 저장되어 있는지 Big Endian으로 저장되어 있는지 알려준다. (Little Endian0, Big Endian1로 매겨진다.)
Endian (Endianness) 메모리처럼 1차원 공간이 주어졌을 때, 요소들을 연속적으로 배치하는 방법을 Endian이라고 한다. 이 때 바이트 단위로 배치하는 것을 Byte Order라고 한다. Byte Order로 메모리 상에 요소들을 두려고 할 때, 큰 단위가 먼저 표현되는 것이 Big Endian이고 작은 단위가 먼저 표현되는 것이 Little Endian이 된다. 둘 다 지원을 하거나 둘 다 지원하지 않는 경우에는 Middle Endian이라 부른다. 일반적으로 사람들이 숫자를 표기할 때 사용하는 방법이 Big Endian이다. Byte Order에 따른 Big EndianLittle Endian의 예를 살펴보자. Big Endian Little Endian 0x1234 → 12 34 34 12 0x12345678 → 12 34 56 78 78 56 34 12

반환 값

메모리 상에 있는 Image의 주소를 반환 (mlx_new_imageImage Identifier를 반환했던 것과 다른 것이다.)

참고

mlx_get_data_addr 함수는 메모리 상에 존재하도록 생성된 Imagebits_per_pixel, size_line, endian과 같은 여러 정보들을 갖다주는 함수이다. 넘겨 받은 정보들은 프로그래머가 Image를 조작하기 쉽게 만들어준다.
예를 들어 bits_per_pixel의 값이 8이라고 한다면, mlx_get_data_addr로 반환 받은 Image의 주소 값에서 8 비트만큼이 Image의 첫 행의 첫 Pixel의 색상을 나타내는 값이 된다. 따라서 그 다음 8 비트Image의 첫 행의 두 번째 Pixel의 색상을 나타내는 값으로 이어진다. 반환된 Image 주소 값에 size_line만큼을 더하게 되면 Image의 두 번째 행의 시작 지점이 된다. 따라서 bits_per_pixelsize_line을 이용하면 Image에 존재하는 어떤 Pixel에도 접근이 가능하게 된다.

3) mlx_put_image_to_window

함수 원형

int mlx_put_image_to_window(void *mlx_ptr, void *win_ptr, void *img_ptr, int x, int y);
C
복사

함수 인자

Screen Connection에 해당하는 Window를 찾기 위해 mlx_ptrwin_ptr이 사용된다. mlx_ptrImage Identifierimg_ptr을 이용하여 Screen Connection에 유지 중인 Image를 찾아낸다. WindowImage를 찾아냈으면, ImageWindow(x,y)(x, y) 좌표에 위치시키면서 디스플레이 장치에 나타낼 수 있도록 만든다.

반환 값

함수의 원형에서는 int 타입의 반환 값을 갖는다고 하지만, SwiftForwarding되고 있는 Interface를 직접 확인해보면 아래 코드와 같이 단순히 0을 반환하는 것을 확인할 수 있다.
@_cdecl("mlx_put_image_to_window") public func mlx_put_image_to_window_swift(_ mlxptr:UnsafeRawPointer, _ winptr:UnsafeRawPointer, _ imgptr:UnsafeRawPointer, _ x:Int32, _ y:Int32) -> Int32 { let win:MlxWin = _mlx_bridge(ptr:winptr) let img:MlxImg = _mlx_bridge(ptr:imgptr) win.putImage(image:img, x:x, y:y) return Int32(0) }
Swift
복사

참고

mlx_put_image_to_window 함수는 디스플레이 장치에 나타난 WindowImage를 입히는 함수이다.

4) mlx_get_color_value

함수 원형

unsigned int mlx_get_color_value(void *mlx_ptr, int color);
C
복사

함수 인자

mlx_pixel_put 관련 함수들이 사용하는 R, G, B에 대한 4 바이트 표준 표현인 color를 인자로 받는다. 디스플레이 장치에 따라 Pixel의 색상을 표현하기 위한 비트 수가 다르기 때문에 디스플레이 장치에 대한 정보를 얻어서 내부적으로 이용하기 위해 Screen Connection Identifiermlx_ptr을 인자로 받는다.

반환 값

인자로 받은 color 값을 디스플레이 장치의 정보를 통해 생성된 Image가 사용하는 bits_per_pixel만큼의 크기로 변환하여 unsigned int 타입으로 반환 (반환된 값이 디스플레이 장치에서 실제로 이용되는 색상 값이라고 보면 된다.)

참고

mlx_get_color_value 함수는 사용자가 표준을 따르도록 정의한 color 값이 실제 디스플레이 장치에서 어떤 값으로 사용되는지 알아내기 위한 함수이다.
Image 자체가 디스플레이 장치에 대한 정보들로 생성이 되기 때문에 bits_per_pixelImage에도 존재할 수 있는 것이다.
mlx_pixel_put 관련 함수들이 이용하는 색상 값은 4 바이트이지만 투명도를 이용하고 있지 않기 때문에, bits_per_pixel24 비트 혹은 32 비트라면 별도의 변환이 필요 없다. 즉, 이런 경우에는 mlx_get_color_value를 사용할 필요가 없어진다.
X11과 같이 ImageEndian과 로컬 머신의 Endian이 다르게 사용되는 경우에는, Endian 값을 적절히 변환 해줘야 해당 함수 호출 뿐 아니라 다른 작업에 대해서도 올바른 결과 값을 얻을 수 있다.

5) mlx_xpm_to_image

함수 원형

void *mlx_xpm_to_image(void *mlx_ptr, char **xpm_data, int *width, int *height);
C
복사

함수 인자

mlx_xmp_to_image의 함수 정의를 살펴보면, xpm_data를 이용하여 단순히 mlx_int_parse_xpm을 호출하는 것을 확인할 수 있다. 그리고 mlx_int_parse_xpm을 확인해보면 내부적으로 mlx_new_image를 호출하는 것을 볼 수 있는데, mlx_ptrmlx_new_image 호출에 사용된다. Image의 크기는 widthheight 만큼으로 유지된다.
void *mlx_int_parse_xpm(void *xvar,void *info,int info_size,char *(*f)(), int *width, int *height) { // ... 중략 if (!(img = mlx_new_image(xvar,*width,*height))) RETURN; // ... 중략 } void *mlx_xpm_to_image(void *xvar,char **xpm_data,int *width,int *height) { return (mlx_int_parse_xpm(xvar,xpm_data,0,mlx_int_static_line, width, height)); }
C
복사

반환 값

xpm_data를 이용하여 Image 내부를 채우고, 해당 Image 에 대한 식별자를 void * 타입의 포인터로 반환 (반환된 포인터는 라이브러리 내부의 Image 관련 함수들을 호출할 때 사용된다. Image 생성에 실패하게 되면 NULL을 반환한다.)

참고

mlx_xpm_to_image의 반환 값은 img_ptr로 이용되며, Image Identifier라고 불린다. 디스플레이 장치에 맞는 정보들을 이용하여 Image를 생성한다.
MiniLibXXPM 파일을 다루기 위해 표준 XPM 라이브러리를 직접적으로 사용하지 않는 점을 유의한다. (투명도에 대한 처리는 가능하나 모든 XPM 파일을 읽을 수 있는 것은 아니다.)

6) mlx_xpm_file_to_image

함수 원형

void * mlx_xpm_file_to_image(void *mlx_ptr, char *filename, int *width, int *height);
C
복사

함수 인자

mlx_xmp_file_to_image의 함수 정의를 살펴보면, filename에 해당하는 파일로부터 주석을 제거한 데이터들을 얻어서 mlx_int_parse_xpm을 호출하는 것을 확인할 수 있다. 그리고 mlx_int_parse_xpm을 확인해보면 내부적으로 mlx_new_image를 호출하는 것을 볼 수 있는데, mlx_ptrmlx_new_image 호출에 사용된다. Image의 크기는 widthheight 만큼으로 유지된다.
void *mlx_int_parse_xpm(void *xvar,void *info,int info_size,char *(*f)(), int *width, int *height) { // ... 중략 if (!(img = mlx_new_image(xvar,*width,*height))) RETURN; // ... 중략 } void *mlx_xpm_file_to_image(void *xvar,char *file,int *width,int *height) { int fd; int size; char *ptr; void *img; if ((fd = open(file,O_RDONLY))==-1 || (size = lseek(fd,0,SEEK_END))==-1 || (ptr = mmap(0,size,PROT_WRITE|PROT_READ,MAP_PRIVATE,fd,0))== (void *)MAP_FAILED) { if (fd>=0) close(fd); return ((void *)0); } mlx_int_file_get_rid_comment(ptr, size); img = mlx_int_parse_xpm(xvar,ptr,size,mlx_int_get_line, width, height); munmap(ptr,size); close(fd); return (img); }
C
복사

반환 값

filename을 이용하여 Image 내부를 채우고, 해당 Image 에 대한 식별자를 void * 타입의 포인터로 반환 (반환된 포인터는 라이브러리 내부의 Image 관련 함수들을 호출할 때 사용된다. Image 생성에 실패하게 되면 NULL을 반환한다.)

참고

mlx_xpm_file_to_image의 반환 값은 img_ptr로 이용되며, Image Identifier라고 불린다. 디스플레이 장치에 맞는 정보들을 이용하여 Image를 생성한다.
MiniLibXXPM 파일을 다루기 위해 표준 XPM 라이브러리를 직접적으로 사용하지 않는 점을 유의한다. (투명도에 대한 처리는 가능하나 모든 XPM 파일을 읽을 수 있는 것은 아니다.)

7) mlx_png_file_to_image

함수 원형

void *mlx_png_file_to_image(void *mlx_ptr, char *filename, int *width, int *height);
C
복사

함수 인자

mlx_png_file_to_image의 함수 정의를 살펴보면, filename에 해당하는 파일로부터 데이터들을 얻어서 mlx_int_parse_png을 호출하는 것을 확인할 수 있다. 그리고 mlx_int_parse_png을 확인해보면 내부적으로 mlx_new_image를 호출하는 것을 볼 수 있는데, mlx_ptrmlx_new_image 호출에 사용된다. Image의 크기는 widthheight 만큼으로 유지된다.
void *mlx_int_parse_png(void *xvar, unsigned char *fptr, int size, int *width, int *height) { // ... 중략 if (!(img = mlx_new_image(xvar, pi.width, pi.height))) { warnx("mlx PNG error : Can't create mlx image"); return ((void *)0); } // ... 중략 } void *mlx_png_file_to_image(void *xvar, char *file, int *width, int *height) { int fd; int size; unsigned char *ptr; void *img; if ((fd = open(file, O_RDONLY)) == -1 || (size = lseek(fd, 0, SEEK_END)) == -1 || (ptr = mmap(0, size, PROT_READ, MAP_PRIVATE, fd, 0)) == (void *)MAP_FAILED) { if (fd >= 0) close(fd); warnx("Can't map png file '%s'", file); return ((void *)0); } if (!(img = mlx_int_parse_png(xvar, ptr, size, width, height))) { *width = 0; *height = 0; } munmap(ptr,size); close(fd); return (img); }
C
복사

반환 값

filename을 이용하여 Image 내부를 채우고, 해당 Image 에 대한 식별자를 void * 타입의 포인터로 반환 (반환된 포인터는 라이브러리 내부의 Image 관련 함수들을 호출할 때 사용된다. Image 생성에 실패하게 되면 NULL을 반환한다.)

참고

mlx_png_file_to_image의 반환 값은 img_ptr로 이용되며, Image Identifier라고 불린다. 디스플레이 장치에 맞는 정보들을 이용하여 Image를 생성한다.
MiniLibXPNG 파일을 다루기 위해 표준 PNG 라이브러리를 직접적으로 사용하지 않는 점을 유의한다. (투명도에 대한 처리는 가능하나 모든 PNG 파일을 읽을 수 있는 것은 아니다.)

8) mlx_destroy_image

함수 원형

int mlx_destroy_image(void *mlx_ptr, void *img_ptr);
C
복사

함수 인자

Screen Connection 상에서 유지 중인 Image를 지울 수 있도록, mlx_ptrimg_ptr을 인자로 받는다.

반환 값

함수의 원형에서는 int 타입의 반환 값을 갖는다고 하지만, SwiftForwarding되고 있는 Interface를 직접 확인해보면 아래 코드와 같이 단순히 0을 반환하는 것을 확인할 수 있다.
@_cdecl("mlx_destroy_image") public func mlx_destroy_image_swift(_ mlxptr:UnsafeRawPointer, _ imgptr:UnsafeRawPointer) -> Int32 { let mlx:MlxMain = _mlx_bridge(ptr:mlxptr) /// bridge_transfer to get the retain, at end of this func should release the MlxImg object, because no ref anymore. let img:MlxImg = _mlx_bridge_transfer(ptr:imgptr) mlx.winList.forEach { $0.flushImages() } while img.onGPU > 0 {} mlx.imgList.removeAll(where: { $0 === img} ) return Int32(0) }
Swift
복사

참고

mlx_destroy_image 함수는 Image를 소멸시키는 함수이다.

4. mlx_pixel_put

mlx_pixel_put 관련 함수들은 Window 내부를 그려내는데 사용된다.

1) 색상 관리

mlx를 이용하여 색상을 표현하기 위해선 사전에 정의된 형식에 맞춰 int 타입으로 만들어야 한다. int 타입으로 만든 색상은 이를 이루는 3가지 기본 색상인 R (빨강), G (초록), B (파랑)에 대한 정보를 포함한다. 각 R, G, B0x2550 ≤ x ≤ 255의 값을 가질 수 있으며, 이 값은 원 색상을 표현하기 위해 얼만큼의 비중을 차지하는지를 의미한다. 0x2550 ≤ x ≤ 255는 총 256개므로 282^88 비트로 표현할 수 있는데, 이는 곧 각 R, G, B1 바이트씩 차지한다는 것을 의미한다. int 타입은 일반적으로 4 바이트이므로, R, G, B에 대한 정보를 포함할 수 있다. 그 형식은 아래와 같다.
하드웨어 능력에 따라서 아래 형식의 MSB에 해당하는 0이 투명도를 나타내는데 사용될 수 있지만, 클래식한 OpenGL과는 달리 여기선 투명도를 나타내지 않는다. 투명도를 나타내는 방법은 OpacityTransparency (Alpha)가 있다. Opacity는 일반적으로 0.0x1.00.0 ≤ x ≤ 1.0의 값을 갖고 이를 이용하는 방식을 RGBO라고 한다. Alpha0x2550 ≤ x ≤ 255의 값을 갖고 이를 이용하는 방식을 ARGB라고 한다.
| 0 | R | G | B | color integer +---+---+---+---+ MSB LSB 0x 00 RR GG BB R 0x 00 FF 00 00 G 0x 00 00 FF 00 B 0x 00 00 00 FF
C
복사
이를 통해 색상을 생성하거나 특정 색상 요소를 추출하는 간단한 함수를 만들어볼 수 있다.
int encode_rgb(int r, int g, int b) { return (r << 16 | g << 8 | b); }
C
복사
int decode_r(int color) { return (color & 0x00FF0000); } int decode_g(int color) { return (color & 0x0000FF00); } int decode_b(int color) { return (color & 0x000000FF); }
C
복사
encode_rgb의 호출부에서 r, g, b 인자 값을 0x2550 ≤ x ≤ 255의 값을 주는 것이 아니라 Opacity처럼 Normalize0.0x1.00.0 ≤ x ≤ 1.0의 값을 주는 경우가 허다한데 이 때는 아래와 같이 0x2550 ≤ x ≤ 255의 값을 이용할 수 있도록 Scale 해주면 된다.
RT 구현에 따라서 색상 값을 Gamma Correction에 따라 Scale할 수도 있고, 위와 같이 Normalize된 값을 이용할 때 최대 및 최소 범위를 넘어가는 값이 들어오면 이를 Clamp할 수도 있어야 한다. 이에 대한 구현은 encode_rgb 함수 혹은 색상 값을 직접적으로 쓰는 함수에서 추가적으로 작성하여 색상 값 이용에 대한 엄격한 관리를 하는 것이 좋다.
int r; int g; int b; int color; // set r, g, b value // r = 0.1; // g = 0.2; // b = 0.3; color = encode_rgb(255.999 * r, 255.999 * g, 255.999 * b);
C
복사

2) mlx_pixel_put

함수 원형

int mlx_pixel_put(void *mlx_ptr, void *win_ptr, int x, int y, int color);
C
복사

함수 인자

Window를 의미하는 win_ptr을 인자로 받고, 이 Window를 찾아서 작업을 수행할 수 있도록 Window를 관리하는 mlx_ptr도 인자로 받는다. 인자로 받은 xy를 좌표로 하는 Pixel 위에 color에 해당하는 색상을 입힌다.

반환 값

함수의 원형에서는 int 타입의 반환 값을 갖는다고 하지만, SwiftForwarding되고 있는 Interface를 직접 확인해보면 아래 코드와 같이 아무런 반환 값이 없는 것을 확인할 수 있다.
@_cdecl("mlx_pixel_put") public func mlx_pixel_put_swift(_ mlxptr:UnsafeRawPointer, _ winptr:UnsafeRawPointer, _ x:Int32, _ y:Int32, _ color:UInt32) { let win:MlxWin = _mlx_bridge(ptr:winptr) win.pixelPut(x, y, color) }
Swift
복사

참고

좌측 상단의 코너를 원점인 (0,0)(0, 0)으로 간주한다. (x,y)(x, y)는 원점을 기준으로 우측 하단 쪽에 위치하게 된다. Window를 벗어난 위치에 대한 작업은 버리게 되고, 이런 작업은 mlx_pixel_put에 대한 처리를 느리게 만든다. 일일이 mlx_pixel_put을 호출하는 것보다는 Image를 이용하는 작업을 고려하는 것이 권장된다.

3) mlx_string_put

함수 원형

int mlx_string_put(void *mlx_ptr, void *win_ptr, int x, int y, int color, char *string);
C
복사

함수 인자

Window를 의미하는 win_ptr을 인자로 받고, 이 Window를 찾아서 작업을 수행할 수 있도록 Window를 관리하는 mlx_ptr도 인자로 받는다. 인자로 받은 xy를 좌표로 하는 Pixel 위에 color에 해당하는 색상을 입히고 string에 해당하는 문자열을 나타낸다.

반환 값

함수의 원형에서는 int 타입의 반환 값을 갖는다고 하지만, C 언어로 작성된 코드를 직접 확인해보면 아래 코드와 같이 단순히 0을 반환하는 것을 확인할 수 있다.
int mlx_string_put(void *mlx_ptr, void *win_ptr, int x, int y, int color, char *string) { static void *font = (void *)0; static unsigned char *data = (void *)0; static int size_line = 0; int bpp; int endian; int pos; int val; int dest_w; int dest_h; if (font == (void *)0) { font = mlx_new_image(mlx_ptr, font_atlas.width, font_atlas.height); data = (unsigned char *)mlx_get_data_addr(font, &bpp, &size_line, &endian); mlx_int_fill(data, size_line); } color = (color&0xFFFFFF)|0xFF000000; // dest_w = (FONT_WIDTH*5)/7; /// ratio with X11 standard mlx_string_put // dest_h = (font_atlas.height*5)/7; dest_w = FONT_WIDTH; dest_h = font_atlas.height; y = y - (dest_h*3)/4; pos = 0; while (*string) { if (*string >= 32 && *string <= 127) val = *string - 32; else val = 31; mlx_put_image_to_window_scale(mlx_ptr, win_ptr, font, val*(FONT_WIDTH+2), 0, FONT_WIDTH, font_atlas.height, x+pos*dest_w, y, dest_w, dest_h, color); pos ++; string ++; } return (0); }
C
복사

참고

좌측 상단의 코너를 원점인 (0,0)(0, 0)으로 간주한다. (x,y)(x, y)는 원점을 기준으로 우측 하단 쪽에 위치하게 된다. Window를 벗어난 위치에 대한 작업은 버리게 되고, 이런 작업은 mlx_string_put에 대한 처리를 느리게 만든다. 일일이 mlx_string_put을 호출하는 것보다는 Image를 이용하는 작업을 고려하는 것이 권장된다.

5. mlx_loop

mlx_loop 관련 함수들은 키보드 혹은 마우스에 대한 Event를 관리하고 처리하는데 이용된다.
Event 그래픽 시스템은 양방향성을 갖는다. 한 쪽에서는 WindowPixel 혹은 Image 을 나타내달라는 요청을 보내게 되고, 다른 한 쪽은 Window에서 사용된 마우스 혹은 키보드를 이용한 정보들을 취득한다. 여기서 마우스 혹은 키보드를 이용한 정보를 Event라 한다. 따라서 프로그램은 Event를 캐치해서 그래픽 시스템에게 보내 Event를 처리할 수 있도록 해야하는데 이 과정을 "mlx.h"mlx_loop가 담당한다. mlx_initmlx_new_window만으로는 그래픽 시스템에 대한 접근이 불가능하기 때문에 바로 Window가 종료된다. 따라서 mlx_loop까지 이용해야 Window에서의 Event를 관리 및 처리할 수 있을 뿐 아니라 그래픽 시스템에 대한 접근이 가능하여 Window를 지속할 수 있게 된다. Event를 캐치하여 그래픽 시스템에 접근할 수 있도록 만들어주는 mlx_loop를 사용하기 전, 어떤 Event를 캐치할지 명시함으로써 mlx_loop가 프로그램을 종료시키지 않고 계속해서 동작할 때 정상적인 기능을 하도록 만들 수 있다. "mlx.h"는 다양한 Event들을 캐치할 수 있도록 함수들을 제공하는데, 이 함수들은 mlx_*_hook의 이름을 갖는다. mlx_*_hook 함수들은 mlx_hook을 통해서 공통적인 형식으로 이용될 수 있다. mlx_hookX11"X.h"에 존재하는 EventMask 값을 이용한다. Mac OS XEvent들은 대체적으로 X11Event 값들에 Mapping되어 있으며, Mac OS X 상에서 Mask 값은 사용되지 않는다.
Hooking & Hook Hooking이라는 것은 Software를 구성하고 있는 요소 간에 전달된 Function, Message, Event 등을 가로채는 것을 의미하고 Hooking을 수행하는 코드를 Hook이라 한다. mlx_loopEvent를 처리할 수 있도록 어떤 Event를 캐치할지 명시할 때 mlx_*_hook을 사용한다고 했는데, mlx_*_hook의 코드가 Hook을 의미하고 함수의 동작이 곧 Hooking을 의미한다. HookingFunction, Message, Event 등은 Software의 다른 구성 요소 동작에 영향을 끼치게 된다.

1) mlx_loop

함수 원형

int mlx_loop(void *mlx_ptr);
C
복사

함수 인자

어떤 Screen ConnectionEvent를 처리할지 Screen Connection Identifier를 명시한다.

반환 값

함수의 원형에서는 int 타입의 반환 값을 갖는다고 하지만, SwiftForwarding되고 있는 Interface를 직접 확인해보면 아래 코드와 같이 아무런 반환 값이 없는 것을 확인할 수 있다.
@_cdecl("mlx_loop") public func mlx_loop_swift(_ mlxptr:UnsafeRawPointer) { let mlx:MlxMain = _mlx_bridge(ptr:mlxptr) mlx.inLoop = true NSApp.run() }
Swift
복사

참고

mlx_loop 함수는 반환을 절대로 하지 않도록 Infinite Loop를 갖고 있는 함수이다. 등록된 Hook 함수들에 따라 Event를 캐치하여 처리하도록 무한히 반복한다. Event를 캐치하면 Hook 함수에 등록된 Callback Function을 호출함으로써 Event를 처리한다.

2) mlx_key_hook

함수 원형

int mlx_key_hook(void *win_ptr, int (*funct_ptr)(), void *param);
C
복사

함수 인자

키보드 버튼에 대한 Event가 발생했을 때 Callback Function을 호출할 수 있도록 funct_ptr라는 함수 포인터를 인자로 이용한다. param이라는 인자는 funct_ptr을 통해 Callback Function이 호출되었을 때, Callback Function의 인자로써 이용된다. (포인터로 param을 넘겼기 때문에 Callback Function 호출을 통해 특정 값을 수정하는 것도 가능하고, param을 구조체로써 이용하면 구조체 내부의 여러 값들을 인자로써 활용하는 것도 가능하다.) 해당 함수는 Window Identifier를 이용한다.

반환 값

함수의 원형에서는 int 타입의 반환 값을 갖는다고 하지만, SwiftForwarding되고 있는 Interface를 직접 확인해보면 아래 코드와 같이 단순히 0을 반환하는 것을 확인할 수 있다.
@_cdecl("mlx_key_hook") public func mlx_key_hook_swift(_ winptr:UnsafeRawPointer, _ fctptr:UnsafeMutableRawPointer, _ paramptr:UnsafeMutableRawPointer) -> Int32 { let win:MlxWin = _mlx_bridge(ptr:winptr) win.addHook(index: 3, fct: fctptr, param: paramptr) return (Int32(0)); }
Swift
복사

참고

키보드 버튼에 대한 Event가 발생하면 MiniLibXCallback Function으로 동작하는 함수를 아래와 같은 형태로 호출하기 때문에 mlx_key_hookfunct_ptr은 아래와 같은 형태의 함수를 참조하도록 만들어 인자로 사용해야 한다. (함수의 이름은 임의로 작성한 것이다.)
int key_hook(int keycode, void *param);
C
복사
MiniLibX가 이렇게 처리를 하는 것 뿐이지 위의 함수를 MiniLibX가 제공하는 것은 아니기 때문에 인자로 사용되는 paramMiniLibX의 동작에 의해 제어되는 것이 아니다. 또한 인자로 사용되는 keycodeX11"keysymdef.h"에 정의된 값을 따른다.
MiniLibX가 처리하는 함수들은 Event를 구분하여 동작시키기 위해 함수의 원형만 다를 뿐, 내부적으로는 mlx_mouse_hook, mlx_expose_hook도 동일하게 동작한다.
동일한 Screen Connection을 이용하더라도, mlx_key_hook 함수는 Screen Connection 단위가 아닌 Window 단위로 처리므로 여러 Window에 대해 mlx_key_hook 함수 이용이 가능하다.
keycode는 아래와 같이 이용된다.

3) mlx_mouse_hook

함수 원형

int mlx_mouse_hook(void *win_ptr, int (*funct_ptr)(), void *param);
C
복사

함수 인자

마우스 버튼에 대한 Event가 발생했을 때 Callback Function을 호출할 수 있도록 funct_ptr라는 함수 포인터를 인자로 이용한다. param이라는 인자는 funct_ptr을 통해 Callback Function이 호출되었을 때, Callback Function의 인자로써 이용된다. (포인터로 param을 넘겼기 때문에 Callback Function 호출을 통해 특정 값을 수정하는 것도 가능하고, param을 구조체로써 이용하면 구조체 내부의 여러 값들을 인자로써 활용하는 것도 가능하다.) 해당 함수는 Window Identifier를 이용한다.

반환 값

함수의 원형에서는 int 타입의 반환 값을 갖는다고 하지만, SwiftForwarding되고 있는 Interface를 직접 확인해보면 아래 코드와 같이 단순히 0을 반환하는 것을 확인할 수 있다.
@_cdecl("mlx_mouse_hook") public func mlx_mouse_hook_swift(_ winptr:UnsafeRawPointer, _ fctptr:UnsafeMutableRawPointer, _ paramptr:UnsafeMutableRawPointer) -> Int32 { let win:MlxWin = _mlx_bridge(ptr:winptr) win.addHook(index: 4, fct: fctptr, param: paramptr) return (Int32(0)); }
Swift
복사

참고

마우스 버튼에 대한 Event가 발생하면 MiniLibXCallback Function으로 동작하는 함수를 아래와 같은 형태로 호출하기 때문에 mlx_mouse_hookfunct_ptr은 아래와 같은 형태의 함수를 참조하도록 만들어 인자로 사용해야 한다. (함수의 이름은 임의로 작성한 것이다.)
int mouse_hook(int button, int x, int y, void *param);
C
복사
MiniLibX가 이렇게 처리를 하는 것 뿐이지 위의 함수를 MiniLibX가 제공하는 것은 아니기 때문에 인자로 사용되는 paramMiniLibX의 동작에 의해 제어되는 것이 아니다. 또한 인자로 사용되는 x, yWindow 상에서의 좌표를 나타내며, button은 마우스의 어떤 버튼을 눌렀는지를 의미한다.
MiniLibX가 처리하는 함수들은 Event를 구분하여 동작시키기 위해 함수의 원형만 다를 뿐, 내부적으로는 mlx_key_hook, mlx_expose_hook도 동일하게 동작한다.
동일한 Screen Connection을 이용하더라도, mlx_mouse_hook 함수는 Screen Connection 단위가 아닌 Window 단위로 처리므로 여러 Window에 대해 mlx_mouse_hook 함수 이용이 가능하다.

4) mlx_expose_hook

함수 원형

int mlx_expose_hook(void *win_ptr, int (*funct_ptr)(), void *param);
C
복사

함수 인자

Window의 일부분을 다시 그려야 하는 Event가 발생했을 때 Callback Function을 호출할 수 있도록 funct_ptr라는 함수 포인터를 인자로 이용한다. param이라는 인자는 funct_ptr을 통해 Callback Function이 호출되었을 때, Callback Function의 인자로써 이용된다. (포인터로 param을 넘겼기 때문에 Callback Function 호출을 통해 특정 값을 수정하는 것도 가능하고, param을 구조체로써 이용하면 구조체 내부의 여러 값들을 인자로써 활용하는 것도 가능하다.) 해당 함수는 Window Identifier를 이용한다.

반환 값

함수의 원형에서는 int 타입의 반환 값을 갖는다고 하지만, SwiftForwarding되고 있는 Interface를 직접 확인해보면 아래 코드와 같이 단순히 0을 반환하는 것을 확인할 수 있다.
@_cdecl("mlx_expose_hook") public func mlx_expose_hook_swift(_ winptr:UnsafeRawPointer, _ fctptr:UnsafeMutableRawPointer, _ paramptr:UnsafeMutableRawPointer) -> Int32 { let win:MlxWin = _mlx_bridge(ptr:winptr) win.addHook(index: 12, fct: fctptr, param: paramptr) return (Int32(0)); }
Swift
복사

참고

Unix 계열의 운영체제에서 X11GUI 환경을 이용하게 되면 Window의 일부분을 다시 그리는 요청을 처리하는 것은 프로그램의 몫이다. 하지만 Mac OS XX11을 이용하지 않기 때문에 Mac OS X 상에서는 발생하지 않는 Event이다. 따라서 Mac OS X 상에서는 mlx_expose_hook 함수를 호출할 필요가 없다.
Window의 일부분을 다시 그려야 하는 Event가 발생하면 MiniLibXCallback Function으로 동작하는 함수를 아래와 같은 형태로 호출하기 때문에 mlx_expose_hookfunct_ptr은 아래와 같은 형태의 함수를 참조하도록 만들어 인자로 사용해야 한다. (함수의 이름은 임의로 작성한 것이다.)
int expose_hook(void *param);
C
복사
MiniLibX가 이렇게 처리를 하는 것 뿐이지 위의 함수를 MiniLibX가 제공하는 것은 아니기 때문에 인자로 사용되는 paramMiniLibX의 동작에 의해 제어되는 것이 아니다.
MiniLibX가 처리하는 함수들은 Event를 구분하여 동작시키기 위해 함수의 원형만 다를 뿐, 내부적으로는 mlx_key_hook, mlx_mouse_hook도 동일하게 동작한다.
동일한 Screen Connection을 이용하더라도, mlx_expose_hook 함수는 Screen Connection 단위가 아닌 Window 단위로 처리므로 여러 Window에 대해 mlx_expose_hook 함수 이용이 가능하다.

5) mlx_hook

함수 원형

int mlx_hook(void *win_ptr, int x_event, int x_mask, int (*funct)(), void *param);
C
복사

함수 인자

x_eventx_maskEvent를 설명하는 값들이다. 다른 Hook 함수들과 마찬가지로 Event가 발생했을 때 Callback Function을 호출할 수 있도록 funct라는 함수 포인터를 인자로 이용한다. param이라는 인자는 funct을 통해 Callback Function이 호출되었을 때, Callback Function의 인자로써 이용된다. (포인터로 param을 넘겼기 때문에 Callback Function 호출을 통해 특정 값을 수정하는 것도 가능하고, param을 구조체로써 이용하면 구조체 내부의 여러 값들을 인자로써 활용하는 것도 가능하다.) 해당 함수는 Window Identifier를 이용한다.

반환 값

함수의 원형에서는 int 타입의 반환 값을 갖는다고 하지만, SwiftForwarding되고 있는 Interface를 직접 확인해보면 아래 코드와 같이 단순히 0을 반환하는 것을 확인할 수 있다.
@_cdecl("mlx_hook") public func mlx_hook_swift(_ winptr:UnsafeRawPointer, _ xevent:Int32, _ xmask:Int32, _ fctptr:UnsafeMutableRawPointer, _ paramptr:UnsafeMutableRawPointer) -> Int32 { let win:MlxWin = _mlx_bridge(ptr:winptr) win.addHook(index: Int(xevent), fct: fctptr, param: paramptr) return (Int32(0)); }
C
복사

참고

매뉴얼 파일에는 명시되어 있지 않은 함수지만, "mlx.h"를 살펴보면 존재하는 함수이다. mlx_key_hook, mlx_mouse_hook, mlx_expose_hook과 같은 Hook 함수들을 사용하지 않고 mlx_hook이라는 함수만으로 키보드 버튼, 마우스 버튼, 일부 화면 그리기 등의 Event를 모두 등록할 수 있다.
x_eventx_mask 값은 X11"X.h"를 참고해보면 그 값들이 상세히 정의되어 있는 것을 확인할 수 있으므로 원하는 Event에 대한 값을 이용하면 된다. 단, Mac OS X에서는 Mask 값이 사용되지 않는다고 했기 때문에 x_mask 값을 0으로 지정하여 사용하지 않는 인자임을 암시하도록 하여도 내부적으로는 사용하지 않아 동작에는 지장이 없다. Unix 계열의 운영체제와의 이식성을 위해 x_mask 값을 명시할 것인지, Mac OS X 상에서만 동작시킬 목적으로 이용하지 않는 값임을 명시할 것인지는 프로그래머의 몫이 되겠다.

6) mlx_loop_hook

함수 원형

int mlx_loop_hook(void *mlx_ptr, int (*funct_ptr)(), void *param);
C
복사

함수 인자

등록된 Event들이 발생하지 않으면 Callback Function을 호출할 수 있도록 funct_ptr라는 함수 포인터를 인자로 이용한다. param이라는 인자는 funct_ptr을 통해 Callback Function이 호출되었을 때, Callback Function의 인자로써 이용된다. (포인터로 param을 넘겼기 때문에 Callback Function 호출을 통해 특정 값을 수정하는 것도 가능하고, param을 구조체로써 이용하면 구조체 내부의 여러 값들을 인자로써 활용하는 것도 가능하다.) 해당 함수는 Screen Connection Identifier를 이용한다.

반환 값

함수의 원형에서는 int 타입의 반환 값을 갖는다고 하지만, SwiftForwarding되고 있는 Interface를 직접 확인해보면 아래 코드와 같이 단순히 0을 반환하는 것을 확인할 수 있다.
@_cdecl("mlx_loop_hook") public func mlx_loop_hook_swift(_ mlxptr:UnsafeRawPointer, _ fctptr:UnsafeMutableRawPointer, _ paramptr:UnsafeMutableRawPointer) -> Int32 { let mlx:MlxMain = _mlx_bridge(ptr:mlxptr) mlx.addLoopHook(fctptr, paramptr) return (Int32(0)); }
Swift
복사

참고

mlx_loop_hook 함수는 Event에 대해 Hooking을 수행하는 mlx_key_hook, mlx_mouse_hook, mlx_expose_hook와 대체적으로 동일한 인자를 받지만, mlx_ptr을 받는 것으로 보아 Window 단위가 아닌 Screen Connection 단위로 동작하는 것을 알 수 있고 Event가 발생하지 않았을 때 반복적으로 호출되어 수행되는 함수라는 측면에서 Hook 함수들과 다르다는 것을 볼 수 있다.
등록된 Event들이 발생하지 않으면 MiniLibXCallback Function으로 동작하는 함수를 아래와 같은 형태로 호출하기 때문에 mlx_loop_hookfunct_ptr은 아래와 같은 형태의 함수를 참조하도록 만들어 인자로 사용해야 한다. (함수의 이름은 임의로 작성한 것이다.)
int loop_hook(void *param);
C
복사
MiniLibX가 이렇게 처리를 하는 것 뿐이지 위의 함수를 MiniLibX가 제공하는 것은 아니기 때문에 인자로 사용되는 paramMiniLibX의 동작에 의해 제어되는 것이 아니다.
매번의 δ\delta (Delta-Time) 마다 Frame 업데이트를 담당하는 함수라고 볼 수 있다. 해당 함수에 Rendering 관련 로직을 넣고 돌리면 Frame이 업데이트 되는 대로 Window에 나타나는 것을 확인할 수 있다.

6. Reference