 |
파이썬 마을 우리나라 파이썬 사용자들의 이야기 마을
|
|
| 이전 주제 보기 :: 다음 주제 보기 |
| 글쓴이 |
메시지 |
jrcho
가입: 올린 글: 56
|
올려짐: 2004 5월 12 7:26 pm 주제: [SWIG강좌] 3.4 Typemap (1) |
|
|
3.4. Typemap
3.4.1. Why typemap ?
실제로 C/C++ 코드를 Python에서 사용하도록 SWIG를 사용할 경우 형 변환과 관련된 문제에 부딪치게 된다. 예를 들어 다음의 함수를 보길 바란다.
void add(int a, int b, int *result); // result는 출력
add() 함수는 result 인자에 결과값을 받아 온다. 하지만 SWIG는 result의 형이 int *이므로 포인터로 취급하게 된다. 따라서 Python에서
>>> add(1,2,result)
와 같은 호출은 형검사 과정에 오류가 있게 된다. 또한 Python은 함수의 결과값을 함수의 좌측에서 지정한다. 따라서 wrapper를 생성할 때
>>> c = add(1,2);
와 같이 쓸 수 있도록 해야 한다. 이를 위해서는 typemap이라는 것을 이용해야 한다. 위와 같이 Python 인터프리터에서 사용하기 위해서는 wrapper 코드가 다음과 같이 되어야 할 것이고, typemap을 사용하면 만들 수 있다.
static PyObject *_wrap_add(PyObject *self, PyObject *args) {
PyObject *resultobj;
int arg1, arg2 ;
int *arg3;
if(!PyArg_ParseTuple(args,(char *)"ii:add",&arg1,&arg2)) goto fail;
add(arg1,arg2,arg3);
return PyInt_FromLong((long) (*arg3));
}
Typemap의 정확한 정의는 특정 C 데이터 형에 적용되는 코드 생성 규칙으로 사용분야는
- 입출력 변수를 다루거나
- Python 객체를 대응되는 C/C++ 변수로 바꾸거나(tuples,lists, 등)
- SWIG에게 새로운 Python type을 알리거나
-constraint handling추가할 때 사용된다.(the constraint library is really just typemaps).
등이다. Typemap은 매우 방대한 내용이기 때문에 여기서 기본 원리 및 실제 필요한 내용에 대해서만 다루기로 하겠다. SWIG는 C/C++ built-in type에 대한 기본적인 typemap을 담고 있는 표준라이브러리 typemaps.i가 있고, 그 외의 것은 사용자가 직접 작성해야 한다.
3.4.2. typemap basic
typemap은 %typemap 명령으로 SWIG에서 작성한다. 간단한 예로,
%typemap(in) int { ... code ... }
%typemap(out) int { ... code ... }
등이 있다. in, out 은 typemap의 종류를 나타내는 것으로, %typemap(in)은 "in" typemap으로 Python에서 C로 값을 변화시키는 데 사용되는 typemap을 의미하면, %typemap(out)은 "out" typemap으로 Python에서 C로 값을 변화시키는 typemap을 정의한 다는 것이다. %typemap(in), %typemap(out) 다음에는 typemap을 적용할 C 데이터 형(위에서는 int)과 변환하는 코드({...}의 부분)가 따라오게 된다.
다음 예를 보길 바란다. fact1() 함수는 typemap을 적용하지 않는 경우이고, fact2()는 typemap을 적용한 경우이다. fact1() 함수는 typemap을 적용하지 않고 wrapper를 만들고, fact2()는 두개의 typemap을 적용한다. %typemap은 자신이 선언된 이후부터 적용되다. 따라서 fact1()에는 영향을 주지않고, fact2()의 wrapper를 생성할 때만 영향을 준다.
| 코드: |
%module example
int fact1(int n);
%typemap(in) int {
// "in" typemap start
$1 = PyInt_AsLong($input);
// "in" typemap end
}
%typemap(out) int {
// "out" typemap start
$result = PyInt_FromLong($1);
// "out" typemap start
}
int fact2(int n);
|
SWIG를 실행하여 생성된 파일을 살펴보면 다음과 같은 wrapper 함수가 생성되었음을 확인할 수 있다.
| 코드: |
static PyObject *_wrap_fact1(PyObject *self, PyObject *args) {
PyObject *resultobj;
int arg1 ;
int result;
if(!PyArg_ParseTuple(args,(char *)"i:fact1",&arg1)) goto fail;
result = (int)fact1(arg1);
resultobj = PyInt_FromLong((long)result);
return resultobj;
fail:
return NULL;
}
static PyObject *_wrap_fact2(PyObject *self, PyObject *args) {
PyObject *resultobj;
int arg1 ;
int result;
PyObject * obj0 = 0 ;
if(!PyArg_ParseTuple(args,(char *)"O:fact2",&obj0)) goto fail;
{
// "in" typemap start
arg1 = PyInt_AsLong(obj0);
// "in" typemap end
}
result = (int)fact2(arg1);
{
// "out" typemap start
resultobj = PyInt_FromLong(result);
// "out" typemap start
}
return resultobj;
fail:
return NULL;
}
|
위에서 두 함수
long PyInt_AsLong(PyObject *obj); // Python --> C
PyObject *PyInt_FromLong(long x); // C --> Python
는 형변환과 관련된 Python/C API 함수이다. 위에서 typemap으로 작성된 코드는 이 {} 기호 안에서 복사되어 들어간다. 이를 이용해 필요한 형변환을 수행할 수 있다. 각 typemap은 작은 C 코드를 담고 있고, SWIG가 생성하는 wrapper fucntion에 삽입되게 된다. typemap을 정의할 때 $기호로 쓴 변수들은 실제 wrapper를 생성할 때 정해진 규약에 의해 바뀌게 된다. $input은 C로 변환도어야 할 객체를 가르키고, $result 는 wrapper 함수에 의해 리턴되는 객체를 가르킨다. $1 은 typemap 선언에 지정된 것과 동일한 형을 가지는 C 변수(여기서는 int 형을 갖는 변수)를 가르킨다. 이러한 방식으로 typemap은 생성되는 wrapper function에 일정한 규칙을 갖는 코드를 삽입할 수 있도록 해준다.
예에서 알 수 있듯이 typemap은 C wrapper함수를 생성할 때 사용자가 지정한 규칙대로 생성하도록하는 기능을 함을 알 수 있다. 여기에서는 "in" typemap과 "out" typemap을 이용하여 그 원리를 설명하였다. SWIG에서 정의한 typemap에는 상황에따라 사용할 수 있는 typemap이 여러 가지가 있다. 예를 들어 "argout" typemap은 함수의 인자로 리턴값을 받아올때 사용한다. |
|
| 위로 |
|
 |
|
|
새로운 주제를 올릴 수 없습니다 답글을 올릴 수 없습니다 주제를 수정할 수 없습니다 올린 글을 삭제할 수 없습니다 투표를 할 수 없습니다
|
|