ctypes — Python용 외부 함수 라이브러리
ctypes — Python용 외부 함수 라이브러리
ctypes는 Python용 외부 함수(foreign function) 라이브러리입니다. C 호환 데이터 타입을 제공하고 DLL이나 공유 라이브러리의 함수를 호출할 수 있게 해 줍니다. 이 라이브러리들을 순수 Python으로 감싸는 데 사용할 수 있습니다.
본문
ctypes는 선택적(optional) 모듈입니다. CPython 배포본에서 빠져 있다면 배포자(즉, Python을 제공한 사람)의 문서를 찾아보세요. ctypes는 네이티브 라이브러리와 프로세스 메모리에 대한 저수준 접근을 제공하며, Python의 안전 메커니즘을 우회하고 임의의 네이티브 코드 실행을 허용합니다. 잘못 사용하면 데이터와 객체를 손상시키고, 민감한 정보를 노출하며, 크래시를 일으키거나 실행 중인 프로세스를 위협할 수 있으므로 주의해야 합니다.
동적 링크 라이브러리 로딩
ctypes는 동적 링크 라이브러리를 로딩하기 위해 cdll 객체를, Windows에서는 windll과 oledll 객체를 내보냅니다. 이 객체들의 속성으로 라이브러리에 접근하여 로딩합니다. cdll은 표준 cdecl 호출 규약을 사용하는 함수를 내보내는 라이브러리를 로드하고, windll 라이브러리는 stdcall 호출 규약으로 함수를 호출합니다. oledll도 stdcall 규약을 사용하며 함수가 Windows HRESULT 오류 코드를 반환한다고 가정합니다. 이 오류 코드는 함수 호출이 실패하면 자동으로 OSError 예외를 발생시키는 데 사용됩니다 (3.3에서 WindowsError는 OSError의 별칭이 되었고 이제 이 예외가 발생합니다).
Windows 예시:
>>> from ctypes import *
>>> print(windll.kernel32)
<WinDLL 'kernel32', handle ... at ...>
>>> libc = cdll.msvcrt
Windows는 보통 .dll 파일 접미사를 자동으로 붙입니다. 다만 cdll.msvcrt로 표준 C 라이브러리에 접근하면 Python이 사용하는 버전과 호환되지 않는 구버전 라이브러리를 사용할 수 있으므로, 가능하면 네이티브 Python 기능이나 msvcrt 모듈을 사용하는 것이 좋습니다.
다른 시스템은 라이브러리를 로드하려면 확장자를 포함한 파일 이름이 필요하므로 속성 접근으로는 로드할 수 없습니다. dll 로더의 LoadLibrary() 메서드를 사용하거나 CDLL 생성자를 호출해 인스턴스를 만들어 로드해야 합니다. 예를 들어 리눅스에서는:
>>> cdll.LoadLibrary("libc.so.6")
>>> libc = CDLL("libc.so.6")
이렇게 로드된 함수는 C 타입으로 정확한 인자와 반환 타입을 지정해야 제대로 호출할 수 있습니다. ctypes는 c_int, c_char_p, c_void_p, 구조체, 공용체, 배열, 포인터 등 C 호환 데이터 타입을 제공하며, argtypes와 restype 속성으로 함수 시그니처를 선언할 수 있습니다. 이를 통해 C 라이브러리를 순수 Python에서 안전하게 감쌀 수 있습니다.
ctypes 튜토리얼은 로딩에서부터 구조체, 콜백 함수, 자원 관리에 이르기까지 다양한 주제를 다룹니다. 예를 들어 코드 샘플에서 c_int 타입을 참조하는데, sizeof(long) == sizeof(int)인 플랫폼에서는 c_long의 별칭입니다. 따라서 c_int를 기대했다가 c_long이 출력되어도 혼동하지 말아야 합니다. 둘은 사실 같은 타입입니다.