"파이썬에서 C모듈을 이용하기"
*출처 : http://joyholic.kr/122파이썬은 그 자체가 C로 작성되었다.
이런 맥락에서 생각해보면 파이썬에서 C모듈을 사용할수도 있을뿐 아니라 C에서 파이썬 모듈을 사용할수도 있을것 같다. -> 이말은 사실이다.
본론으로 들어가기전에 파일의 확장자에 대해 살포시 살펴보기로 하자.
파일의 확장자는 그 파일의 속성과 종류를 손쉽게 알려주는 역할을 한다. (이는 어떻게 보면 있어도 되고 없어도 되는 존재이며, 관습적으로 사용하게 된다.)
우리가 흔히 알고 있는 확장자로는 'exe', 'txt', 'jpg', 'mp3' 등 수없이 많다.
- lib : 정적 라이브러리 파일, 일반적으로 C, C++ 라이브러리다.
- dll : 동적 라이브러리 파일
- pyd : 파이썬이 사용하는 C 라이브러리
여기서는 C로 작성된 코드를 이용하여 pyd를 만들고 이 pyd를 이용해서 C 모듈을 이용하는 방법에 대해서 살펴본다.
1. 파이썬 코드에서 import를 하면 일어나는 일
파이썬에서 특정한 모듈을 사용하기 위해 import문을 이용하여 모듈을 지정한다. 파이썬이 사용하고 로드하는 모듈은 아래의 순서로 찾고 그와 일치하면 모듈을 초기화한 후에 지역 이름공간에 이름을 정의한다.
- 기본적으로 탑재되어 있는 모듈들 : ex)socket, time 등
- C로 만들어진 dll 파일(윈도에서는 pyd 파일)
- 자체 제작한 파이썬 모듈
그러면 파이썬에서 import는 어떤 매커니즘으로 동작하는가? 이것을 함 알아보자.
import mylib
위의 코드를 수행할때 파이썬은 mylib 모듈을 로드하기 위해 다음의 절차에 따라 검색한다.
- sys.modules 에 등록되어 있는지 확인한다. 등록되어 있으면 로드한다.
- (1)에서 존재하지 않으면 sys.path의 디렉토리를 검색하면서 mylib 모듈을 찾는다.
- 모듈이름과 일치하는 모듈을 찾는다.
- 모듈을 초기화 한다.
- 모듈이름을 지역이름공간에 할당한다.
2. 파이썬에서 이용할 C 모듈 만들기
여기서 우리는 우리가 만든 C 모듈을 파이썬에서 사용하고 싶다. 즉,
import (우리가 만든 C 모듈) 하고 싶다 이 말이다.
우리가 C로 만든 모듈을 파이썬에서 이용하고자 할때 역시 위에서 서술한 import 절차에 따라 모듈을 찾고 로드하게 된다.
우리가 유의해야 할 곳은 바로 모듈을 초기화 하는 부분이다. 나머지 절차는 파이썬이 다 알아서 해준다.
파이썬에서 사용하는 C모듈은 리눅스에서는 .so 확장자 형태로, 윈도에서는 .pyd 확장자 형태로 빌드되어 파이썬 패키지 디렉토리의 Lib/site-package 디렉로리로 복사되므로서 사용가능하게 된다.
그러면 하나의 실제 C모듈을 만들어 적용하므로서 설명해보자.
파이썬이 C 모듈을 import 하게되면 초기화를 위해 "init+모듈이름" 으로 된 함수를 호출한다. 모듈이름이 mylib 이면 initmylib()을 호출한다는 말이다.
그러므로 우리의 C 소스에는 위에서 설명한 초기화를 위한 함수 init+모듈이름 으로 된 함수가 존재해야만 한다.
예제로 만들 모듈은 입력한 문자열을 pylog.txt 라는 파일에 기록하는 모듈이다. 주석을 달았으므로 주석을 참조하도록 한다.
import (우리가 만든 C 모듈) 하고 싶다 이 말이다.
우리가 C로 만든 모듈을 파이썬에서 이용하고자 할때 역시 위에서 서술한 import 절차에 따라 모듈을 찾고 로드하게 된다.
우리가 유의해야 할 곳은 바로 모듈을 초기화 하는 부분이다. 나머지 절차는 파이썬이 다 알아서 해준다.
파이썬에서 사용하는 C모듈은 리눅스에서는 .so 확장자 형태로, 윈도에서는 .pyd 확장자 형태로 빌드되어 파이썬 패키지 디렉토리의 Lib/site-package 디렉로리로 복사되므로서 사용가능하게 된다.
- C로 소스코드를 작성한다.
- 작성한 C 소스코드를 컴파일하여 파이썬이 이용가능한 .so (리눅스에서) 및 .pyd(윈도용) 파일로 빌드한다.
- .so 및 .pyd 파일을 파이썬 디렉토리의 Lib/site-package로 복사한다.
그러면 하나의 실제 C모듈을 만들어 적용하므로서 설명해보자.
파이썬이 C 모듈을 import 하게되면 초기화를 위해 "init+모듈이름" 으로 된 함수를 호출한다. 모듈이름이 mylib 이면 initmylib()을 호출한다는 말이다.
그러므로 우리의 C 소스에는 위에서 설명한 초기화를 위한 함수 init+모듈이름 으로 된 함수가 존재해야만 한다.
예제로 만들 모듈은 입력한 문자열을 pylog.txt 라는 파일에 기록하는 모듈이다. 주석을 달았으므로 주석을 참조하도록 한다.
// mylib.c
#include "Python.h"
#include <stdio.h>
static PyObject *ErrorObject;
// 실제 동작하는 함수
static PyObject* write_log(PyObject *self, PyObject *args) // 인자는 이와같이 고정된다.
{
char* msg;
FILE *fp;
if(!PyArg_ParseTuple(args, "s", &msg))
return NULL;
fp = fopen("c:\\pylog.txt", "wt+");
fprintf(fp, msg);
fclose(fp);
return Py_BuildValue("i", 0);
}
/* methods 구조체 배열에 지정되는 정보는 {"실제사용할 메쏘드명", 메쏘드명에 대응하는 실제 동작하는 함수명, 인자 종류} */
static struct PyMethodDef methods[] =
{
{"wlog", write_log, METH_VARARGS},
{NULL, NULL}
};
//
void initmylib()
{
PyObject* m;
// Py_InitModule("모듈명", 이모듈에 적용된 메쏘드들을 담을 구조체배열 포인터)
m = Py_InitModule("mylib", methods);
ErrorObject = Py_BuildValue("s", "error");
}
위의 C 코드를 컴파일하기 위해 setup.py 함수를 작성해야 한다.
# setup.py
from distutils.core import setup, Extension
setup(name = "mylib",
version = "1.0",
description = "print log",
author = "Samsjang",
author_email = "samsjang@cdnetworks.co.kr",
url = "http://www.cdnetworks.co.kr",
ext_modules = [Extension("mylib", ["mylib.c"])]
)
위의 소스에서 ext_modules에는 적용할 모듈명과 그 모듈의 구현코드를 기록한다. 나머지 부분의 기타 정보를 기록해둔 메타정보에 불과하다.
리눅스 및 윈도에서 아래와 같이 빌드하고 설치한다.
python setup.py install
위의 명령은 리눅스에서는 gcc를 호출하며, 윈도에서는 visual C++ 컴파일러가 구동되면서 빌드한 후 파이썬 디렉토리의 Lib/site-packages 디렉토리에 mylib.so 또는 mylib.pyd 파일이 생성된다.
자 그럼 C모듈인 mylib 모듈을 실제 파이썬 코드에서 적용해보자.
# test.py
import mylib
if __name__ == '__main__':
mylib.wlog('I love U')
위의 결과는 C:\\pylog.txt 파일에 "I love U" 라는 글을 남긴다.
댓글 없음:
댓글 쓰기