.a
형식의 정적 라이브러리를,.dylib
형식의 동적 라이브러리를 생성export DYLD_LIBRARY_PATH=[디렉토리]
echo $DYLD_LIBRARY_PATH
로 확인install_name_tool -change [파일명] [파일 경로] [적용할 파일(프로그램)]
install_name_tool -change libmlx.dylib ./minilibx_mms_20210621/libmlx.dylib test
#include "mlx.h"
int main(void)
{
void *m_ptr;
void *w_ptr;
m_ptr = mlx_init();
w_ptr = mlx_new_window(m_ptr, 1200, 800, "test");
mlx_loop(m_ptr);
return (0);
}
mlx_init
디스플레이와 연결 설정 (초기화)
void *mlx_init();
void *
리턴mlx_new_window
새 창 생성
void *mlx_new_window(void *mlx_ptr, int size_x, int size_y, char *title);
void *
리턴mlx_destroy_window
윈도우 포인터 할당 해제
int mlx_destroy_window(void *mlx_ptr, void *win_ptr);
mlx_loop
창 렌더링
무한 루프를 돌면서 이벤트를 기다림
int mlx_loop(void *mlx_ptr);
Ctrl + C
)CC = gcc
CFLAG = -Wall -Wextra -Werror
NAME = test
SRCS = main.c
OBJS = $(SRCS:.c=.o)
MLXDIR = ./minilibx_mms_20210621
MLXFLAG = -L$(MLXDIR) -lmlx -framework OpenGL -framework AppKit
.PHONY: all
all: $(NAME)
$(OBJS): $(SRCS)
$(CC) $(CFLAG) -I$(MLXDIR) -c $(SRCS)
$(NAME): $(OBJS)
@make -s -C $(MLXDIR)
$(CC) $(CFLAG) $(OBJS) $(MLXFLAG) -o $(NAME)
@install_name_tool -change libmlx.dylib ./minilibx_mms_20210621/libmlx.dylib test
...
#include "mlx.h"
typedef struct s_data
{
void *img;
char *addr;
int bits_per_pixel;
int line_length;
int endian;
} t_data;
void my_mlx_pixel_put(t_data *data, int x, int y, int color)
{
char *dst;
dst = data->addr + (y * data->line_length + x * (data->bits_per_pixel / 8));
*(unsigned int *)dst = color;
}
int main(void)
{
void *mlx;
void *mlx_win;
t_data img;
mlx = mlx_init();
mlx_win = mlx_new_window(mlx, 1200, 800, "test");
img.img = mlx_new_image(mlx, 1200, 800);
img.addr = mlx_get_data_addr(img.img, &img.bits_per_pixel, &img.line_length,
&img.endian);
my_mlx_pixel_put(&img, 5, 5, 0x00FF0000);
mlx_put_image_to_window(mlx, mlx_win, img.img, 0, 0);
mlx_loop(mlx);
return (0);
}
mlx_pixel_put
은 아주 느리고 창이 모두 렌더링되기도 전에 픽셀을 창에 올림char *
에 담긴다.int
로 표현하기 때문에 4 바이트 (bits_per_pixel
은 32)👉 bits_per_pixel
이 32인 경우 1 픽셀은 char
4개로 표현
👉 원하는 픽셀(x, y)의 포인터는 현재 위치에 x * (bits_per_pixel / 8)
과 y * line_length
를 더한 만큼의 위치
ARGB가 0 ~ 255 범위로 1 바이트씩 차지
예) 0x00FF0000
은 빨강
mlx_new_image
새 이미지 생성
void *mlx_new_image(void *mlx_ptr, int width, int height);
void *
리턴mlx_get_data_addr
이미지의 정보 얻기
char *mlx_get_data_addr(void *img_ptr, int *bits_per_pixel, int *size_line, int *endian);
img_ptr
: 이미지 인스턴스 주소bits_per_pixel
: 보통 픽셀은 int
이므로 4 바이트, 즉 32 비트size_line
: 이미지 가로 크기 * 1 픽셀 당 쓰이는 바이트 수 (?)endian
: 엔디안 (0
: 리틀 엔디안(인텔 기본), 1
: 빅 엔디안)mms 라이브러리에서는
size_line
에 패딩값이 추가되어 좀 더 큰 값이 들어간다.
mlx_put_image_to_window
이미지 렌더링
int mlx_put_image_to_window(void *mlx_ptr, void *win_ptr, void *img_ptr, int x, int y);
이벤트가 발생했을 때 OS의 행동을 인터셉트해서 실행하는 코드
(인터셉트한 함수, 이벤트, 메시지 등을 처리하는 코드)
👉 키보드 입력, 마우스 입력, 윈도우 부분 다시 그리기(?)에 사용
#include "mlx.h"
#include <stdio.h>
typedef struct s_vars
{
void *mlx;
void *win;
} t_vars;
int key_hook(int keycode, t_vars *vars)
{
(void)vars;
printf("key hook: %d\n", keycode);
return (0);
}
int main(void)
{
t_vars vars;
vars.mlx = mlx_init();
vars.win = mlx_new_window(vars.mlx, 600, 400, "test");
mlx_key_hook(vars.win, key_hook, &vars);
mlx_loop(vars.mlx);
return (0);
}
- 훅 함수의 인자
win_ptr
: 훅을 적용할 윈도우 주소
funct_ptr
: 키보드 입력 시 실행할 콜백 함수의 주소
param
:funct_ptr
에 전달할 파라미터의 주소- 항상 0 리턴
mlx_key_hook
키보드 이벤트 설정
int mlx_key_hook(void *win_ptr, int (*funct_ptr)(), void *param);
keycode
: 입력된 키의 코드int key_hook(int keycode, void *param);
mlx_mouse_hook
마우스 이벤트 설정
int mlx_mouse_hook(void *win_ptr, int (*funct_ptr)(), void *param);
button
: 입력된 마우스 버튼x
, y
: 현재 창에서의 좌표mouse_hook(int button, int x, int y, void *param);
mlx_hook
모든 이벤트 설정
void mlx_hook(mlx_win_list_t *win_ptr, int x_event, int x_mask, int (*f)(), void *param)
0
으로 고정)enum {
ON_KEYDOWN = 2,
ON_KEYUP = 3,
ON_MOUSEDOWN = 4,
ON_MOUSEUP = 5,
ON_MOUSEMOVE = 6,
ON_EXPOSE = 12,
ON_DESTROY = 17
};
ON_DESTROY
콜백 함수int hook_callback(void *param);
hook 함수들은
mlx_hook
으로 대체하여 사용할 수 있다. 이 때 이벤트들은 X11의X.h
에 있는 이벤트와 마스크 값을 활용한다.
mlx_loop_hook
등록된 이벤트가 발생하지 않았을 때 반복적으로 실행할 함수 등록
👉 각 프레임을 업데이트하여 새로운 화면을 렌더링할 때 사용 (애니메이션)
int mlx_loop_hook(void *mlx_ptr, int (*funct_ptr)(), void *param);
mlx_ptr
를 인자로 받는다.int loop_hook(void *param);
파일을 읽어서 새로운 이미지 생성
xpm
X11에서 사용하는 이미지 확장자
C 언어나 plain text로 되어 있음
...
int main(void)
{
void *mlx;
void *mlx_win;
t_data img;
int img_width;
int img_height;
mlx = mlx_init();
mlx_win = mlx_new_window(mlx, 1200, 800, "test");
img.img = mlx_png_file_to_image(mlx, "img.png", &img_width, &img_height);
img.addr = mlx_get_data_addr(img.img, &img.bits_per_pixel, &img.line_length,
&img.endian);
mlx_put_image_to_window(mlx, mlx_win, img.img, 0, 0);
mlx_loop(mlx);
return (0);
}
mlx_ptr
: mlx 포인터xpm_data
, filename
: 읽어올 xpm 데이터 또는 파일명 (경로는 실행파일 기준)width
, height
: 이미지의 크기를 저장할 변수의 주소mlx_xpm_to_image
void *mlx_xpm_to_image(void *mlx_ptr, char **xpm_data, int *width, int *height);
mlx_xpm_file_to_image
void *mlx_xpm_file_to_image(void *mlx_ptr, char *filename, int *width, int *height);
mlx_png_file_to_image
void *mlx_png_file_to_image(void *mlx_ptr, char *filename, int *width, int *height);
mlx_destroy_image
이미지 포인터 할당 해제
int mlx_destroy_image(void *mlx_ptr, void *img_ptr);
프레임 버퍼링을 직접 관리할 수도 있지만, 2020년 버전부터 mlx_sync
가 지원됨
mlx_sync
는 우리가 데이터를 다 쓰기까지 GPU가 기다리도록 함mlx_sync(MLX_SYNC_IMAGE_WRITABLE, img);
mlx_put_image_to_window(mlx, win, img, 0, 0);
mlx_sync(MLX_SYNC_WIN_CMD_COMPLETED, win);
mlx_sync
효율적인 버퍼 관리를 위한 동기화 기능
#define MLX_SYNC_IMAGE_WRITABLE 1
#define MLX_SYNC_WIN_FLUSH_CMD 2
#define MLX_SYNC_WIN_CMD_COMPLETED 3
int mlx_sync(int cmd, void *param);
cmd
: 위에 정의된 매크로param
: 각 매크로에 맞는 포인터IMG_WRITABLE
: 다음에 실행될 코드들(이미지 변경 사항들)을 버퍼에 저장, 두 번째 파라미터는 이미지 포인터WIN_FLUSH_CMD
: 버퍼에 저장된 데이터를 내보내기 (GPU를 기다리지 않음), 두 번째 파라미터는 윈도우 포인터WIN_CMD_COMPLETED
: 버퍼에 저장된 데이터를 내보내기 (GPU가 완료할 때까지 대기), 두 번째 파라미터는 윈도우 포인터주어진 위치에 텍스트 쓰기
int mlx_string_put(void *mlx_ptr, void *win_ptr, int x, int y, int color, char *string );
https://harm-smits.github.io/42docs/libs/minilibx
https://42kchoi.tistory.com/229
https://bigpel66.oopy.io/library/c/etc/3
https://80000coding.oopy.io/adf8b9d2-475e-4bda-91a2-1d03df9e0d31