Python script
Python을 게임 Script로 활용하자.
2001/07/23 07:23붉은미르
http://www.g-matrix.pe.kr
의 game school에 올린 예제를 중심으로 강의가 구성되어질 것입니다.
다른 님들께서 생각들이나 강의들을 올려주시면 더욱더 감사하겠습니다.
강의자에게 한 마디하기 & 강의 소감 & 고칠 점
- 와.. 멋진 강의 기대할께요~ 2001/07/24 00:48, gryu
- 기대한 만큼 실망도 그 만큼....TT 2001/07/24 11:36 붉은미르
- 어떤 분이던 말투나 어법이 맞지 않은 부분이 있으면 고쳐주세요. 2001/07/30 01:32 붉은미르
- 파이썬을 실제 게임에 적용을 해 봤는데요. 이놈은 근본적으로 임베딩용보다는 지가 메인루프를 가지고 C++ 이나 기타 언어로 최적화시켜서 extension 해 나가도록 되어 있습니다. 임베딩용이라면 훨씬 작고 견고하고 빠른 Lua 가 낫죠. extension 에 관심이 있으신분은 boost.python 이나 기타 extension 용 IDL 들을 찾아보세여~ 후다닥 2003/04/09 9:22 나야나
질문과 답
질문은 가능하면 각 강좌(?)의 끝부분에 해주시고 여기에는 거기에 넣기에 애매하다 싶은 것을 적어주시 바랍니다.
목차
- 파이썬이란?
- 스크립터로 사용할 수 있는 공개용 언어들은 어떤 것들이 있는가?
- 수행능력
- 파이썬에서 Extending and Embedding
- 들어가기 앞서...
- 예제를 실행하기
- C/C++에서 파이썬 함수를 호출하기(예제 중심)
- C/C++에서 파이썬 클래스를 호출하기(예제 중심)
- OpenGL/GLUT 함수를 파이썬에서 호출하자(예제 중심)
- Swing을 이용해서 C++를 파이썬으로 확장하자. => 언제할지 모르겠습니다. (딴 사람이 해도 됩니다.)
- DirectX 를 파이썬에서 호출하자(예제 중심) => 언제할지 모르겠습니다. (딴 사람이 해도 됩니다.)
- Game Script로써 파이썬을 어떻게 활용할 것인가? => 언제할지 모르겠습니다. (딴 사람이 해도 됩니다.)
- 참고자료
파이썬이란?
초고수준, 접착성 언어입니다. 쉽고 단순해서 누구나 쉽게(?) 배울 수 있습니다. 국내에서 작년(2000년)부터 소개되어 인기를 얻고 있는 언어입니다.
저의 어설픈 설명보다는 '파이썬 공식 홈페이지 <http://www.python.org>'을 참조하시면 더욱더 좋을 것입니다. 영어가 부담스러우신 분들은 '한국 파이썬 공식 홈페이지 <http://www.python.or.kr>'을 방문하시면 많은 정보를 얻을 수 있을 것입니다.
스크립터로 사용할 수 있는 공개용 언어들은 어떤 것들이 있는가?
Lua <http://www.lua.org>
CSS <http://http://ibk-software.ch/css/index.html>
Small <http://www.compuphase.com/small.htm>
S-Lang <http://www.s-lang.org/>
Simkin for C++ <http://www.simkin.co.uk/>
Python <http://www.python.org>
ETC....
여기에서 있는 것들은 전부 다 GPG포럼에서 언급되었던 것입니다. 소개해주신분들에게 감사의 말씀을 전해드립니다.
제가 여기에서 가장 주목을 하고 있는 언어는 두개입니다. Lua와 Python입니다. 각각의 쓰임새에 대해서 짧게 설명을 하면 다음과 같이 할 수 있을 것 같습니다.
- 파이쎤
* 비주업 노벨 스타일의 게임 또는 문명 같은 턴 베이스 게임을 만들때에 좋음.
* 게임의 대부분을 파이썬으로 구성하고 속도가 필요한 그래픽부분만 C 또는 C++로 구성함.
* 예가 될지는 모르겠지만.
* 메가폴리(http://www.megafolly.co.kr/)의 LOVE(http://www.my-love.co.kr/)
- 루아
* 임베이디딩을 목적으로 하는 경우에는 가볍고 빨라서 좋음.
* 대부분을 C 또는 C++로 짜고 일부 자주 수정해야 되는 부분만 Lua로 작성함.
* 예가 될지는 모르겠지만.
* MMORPG의 서버에...사용.
수행능력
게임에서 속도라는 것은 상당히 중요한 요소입니다. 아무래 컴이 빨라져서 속도에 신경을 쓰지 않아도 된다고 하지만, 여전히 빠른 속도는 중요합니다. 그럼, 파이썬의 속행 능력은 어느 정도가 될까요? 느려서 사용하기 힘들지 않을까? 쓰고도 남을만큼 충분할까?
이 말로 답을 대신합니다. Blade Of Darkness <http://www.rebelact.net/darkness/> 와 Kingdon Under Fire <http://www.kuf.co.kr/>에 Python이 사용되었다.
파이썬에서 Extending and Embedding
Extending는 C/C++등을 파이썬으로 확장하는 것입니다.
Embedding은 C/C++에서 파이썬을 호출(또는 사용)하는 것입니다.
파이썬을 사용하는 경우에는 Embedding보다는 Extending을 더 많이 사용한다. 즉, 파이썬으로 프로그램을 짠 후 수행능력을 느르면 느린 부분만을 다시 C/C++로 작성한 뒤에 Extending을 해서 파이썬에서 사용하는 방법을 택하는 것이 일반적입니다. 다시금 정리하면,
- 파이썬 => 느린 부분만 C/C++로 작성(Extending) => Extending부분으로 다시 파이썬 작성
그럼 우리는 Extending과 Embedding이 다 필요하다. 그러나, 접근은 Embedding부터하도록 하겠습니다.
들어가기 앞서...
이 글을 읽는 사람은 아래의 경우를 만족한다고 가정합니다.
- Python이 무엇인지 한번은 들어보았다.
- Python을 한번이라도 설치해본 적이 있다.
- Python으로 간단한 프로그램(예, 숫자야구)를 짤 수 있다.
- OpenGL/Glut를 안다.
사실은 이것을 꼭 만족할 필요는 없다.
Python을 대해서 알고 싶은 사람은 맨밑의 '참고자료'를 보기 바랍니다.
그러나, 필히 '참고 자료 -> C 확장 모듈 만들기'은 꼭 읽어보기 바란다.
예제를 실행하기
예제 중심의 강좌이기 때문에 예제 실행될 필요가 있다.
- 파이썬을 설치하면 Release 버젼만 설치된다. Debug버젼을 별도의 절차가 필요하다.
- 임베이딩 파이썬은 실행파일(*.exe), python21.dll(21은 버젼표시임) 과 파이썬 파일(*.py)가 필요하다.
- OpenGL이 지원되는 VGA 카드가 필요하다.
- glut32.dll 이 필요하다.
C/C++에서 파이썬 함수를 호출하기(예제 중심)
우선 예제를 보여주고 각 부분에 대해서 설명을 하는 형식을 취하도록 하겠습니다. Python Embedding에 관한 내용이라고 생각하시면 됩니다.
glEmbed.cpp
// 이 프로그램은 Python을 임베이딩을 하는 것에 대한 간단하 예제이다.
// python이 C형태로 되어있다.
// 간단한 제안이다. 추가적인 확장은 좀더 노력해야될 것 같다.
// 2001/7/18/수
#include <windows.h>
#include <gl/glut.h>
#include 'Python.h'
PyObject *module, *func, *rc;
float g_Ry = 0;
void RenderScene(void)
{
glClear(GL_COLOR_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glColor3f( 1.0f, 1.0f, 1.0f );
glTranslatef( 0.0f, 0.0f, -5.0f );
glRotatef( g_Ry, 0, 1, 0);
glutWireTeapot( 1.0f );
glFlush();
glutSwapBuffers();
}
void Idle()
{
RenderScene();
rc = PyObject_CallObject(func, Py_BuildValue('(f)', g_Ry) );
if (rc == NULL) { PyErr_Print(); }
else {
PyArg_Parse( rc, 'f', &g_Ry );
Py_DECREF(rc);
}
}
void ChangeSize(GLsizei w, GLsizei h)
{
glViewport( 0, 0, w, h);
float fAspect = (GLfloat)w/(GLfloat)h;
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective( 90, fAspect, 1.0f, 5000.0f );
}
void SetupRC(void)
{
glClearColor( 0.0f, 0.0f, 1.0f, 1.0f );
}
void main(int argc, char **argv)
{
glutInitDisplayMode(GLUT_DOUBLE|GLUT_RGB);
glutInitWindowSize( 640, 480);
glutCreateWindow('Embedding Python');
glutDisplayFunc(RenderScene);
glutIdleFunc(Idle);
glutReshapeFunc(ChangeSize);
SetupRC();
Py_Initialize();
PySys_SetArgv( argc, argv);
PyRun_SimpleString('print 'Embedding Python' ');
module = PyImport_ImportModule('teapot');
if (module == NULL) { PyErr_Clear(); printf('Unable to import embed module'); }
func = PyObject_GetAttrString(module, 'move');
if (func == NULL) { PyErr_Clear(); printf('Unable to bind to hello function in detect module '); }
glutMainLoop();
Py_Exit(0);
}
teapot.py
# 임베이딩을 테스트하기 위해서 만들어졌다.
# c형태의 python을 어떻게 임베이딩하는지는 간단하게 배을수 있을 것이다.
def move(a):
a = a + 1
if a > 360: a = 0
return a
우선 glEmbed.cpp을 살펴보기로 하자.
- 선행처리
- #include 'Python.h' => 파이썬을 사용하기 위해서는 필요적으로 포함시켜줘야한다.
- PyObject *module, *func, *rc; => 전역변수
- void main(int argc, char **argv)
- Py_Initialize(); => 파이썬의 시작을 위해서 초기화를 한다.
- PySys_SetArgv( argc, argv );
- PyRun_SimpleString('print 'Embedding Python'
'); => 파이썬 명령어인 'print'를 문자열 단위 실행 함수로 실행시켰다. console창에 'Embedding Python'이라고 출력된다.
-
- module = PyImport_ImportModule('teapot'); => 실행시키고자하는 파이썬의 파일명이다. 이때에는 teapot.py이면 '.py'은 빼고 적는다. ( 개인적으로 파일명단위로 모듈화가 되는 것으로 추정하고 있다.)
- func = PyObject_GetAttrString(module, 'move'); => teapot.py에 있는 함수명이다.
-
- Py_Exit(0); => Py_Initialize();과는 반대로 파이썬 종료를 시킨다.
- void Idle()
- rc = PyObject_CallObject(func, Py_BuildValue('(f)', g_Ry) ); => func즉 move에 float형으로 인자하나(즉, g_Ry)를 넘겨준다는 의미이다. 만약에 float형과 int형 인자가 두개이면 '(fi)'이다.
- PyArg_Parse( rc, 'f', &gRy ); 이것은 PyObject\CallObject에서 리턴되어진 값을 float형으로서 g_Ry에 대입시키는 것이다.
- Py_DECREF(rc); => 이게 중요하다고 하는데 아직을 잘 모르겠다.(무성의한 강의자. ^^;; )
간단하게나만 소스에 대한 개력적인 소개가 끝이 났다.
teapot.py에서 'def move(a):'과 'return a'을 제외한 부분을 얼마던지 바꾸어도 된다.
즉, a = a + 1을 a = a + 4 이런씩으로 바꾸어 그 결과를 지켜보기 바란다.
참고자료에 있는 'C확장 모듈 만들기'를 꼭 읽어보기를 바란다.
C/C++에서 파이썬 클래스를 호출하기(예제 중심)
Python파일을 중점적으로 살펴보기 바란다. 아래의 예제를 실행하기 위해서는 random.pyc가 추가적으로 필요하다.
#include <windows.h>
#include <glglut.h>
#include 'Python.h'
PyObject *module, *request, *func, *rc;
float g_Ry = 0;
void RenderScene(void)
{
glClear(GL_COLOR_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glColor3f( 1.0f, 1.0f, 1.0f );
glTranslatef( 0.0f, 0.0f, -5.0f );
glRotatef( g_Ry, 0, 1, 0);
glutWireTeapot( 1.0f );
glFlush();
glutSwapBuffers();
}
void Idle()
{
RenderScene();
// class에서 method를 호출한다.
rc = PyObject_CallMethod(request, 'wave', 'f', g_Ry);
if (rc == NULL) { PyErr_Print(); }
else {
PyArg_Parse( rc, 'f', &g_Ry );
Py_DECREF(rc);
}
}
void ChangeSize(GLsizei w, GLsizei h)
{
glViewport( 0, 0, w, h);
float fAspect = (GLfloat)w/(GLfloat)h;
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective( 90, fAspect, 1.0f, 5000.0f );
}
void SetupRC(void)
{
glClearColor( 0.0f, 0.0f, 1.0f, 1.0f );
}
void main(void)
{
glutInitDisplayMode(GLUT_DOUBLE|GLUT_RGB);
glutInitWindowSize( 640, 480);
glutCreateWindow('Embedding Python');
glutDisplayFunc(RenderScene);
glutIdleFunc(Idle);
glutReshapeFunc(ChangeSize);
SetupRC();
Py_Initialize();
PyRun_SimpleString('print 'Embedding Python' ');
// teapot_plus.py
module = PyImport_ImportModule('teapot_plus');
if (module == NULL) { PyErr_Clear(); printf('Unable to import embed module'); }
// class name
request = PyObject_CallMethod(module, 'teapot_plus', NULL);
if (request == NULL) { PyErr_Clear(); printf('Unable to bind to teapot_plus function in detect module'); }
glutMainLoop();
Py_Exit(0);
}
# 임베이딩을 테스트하기 위해서 만들어졌다.
# c형태의 python을 어떻게 임베이딩하는지는 간단하게 배을수 있을 것이다.
from random import Random
from time import *
class teapot_plus:
def move(self): # move(self, a)와 move(self)의 위치가 바뀌면 Error가 발생한다. 헐헐헐
a = 30
return a
def move(self, a):
a = a + 1
if a > 360:
a = 0
print a
return a
def wave(self, a):
g = Random(time()) # seed(씨앗)
return g.uniform(-10, 10) + a
앞의 예제와 이번 예제에서 C/C++를 실펴보면 그렇게 크게 변한 것은 못 느낄것이다. 그러나 파이썬을 많은 변화가 있었다.
- c에서
- PyObject_CallMethod 가 사용되었다. 이것은 PyObject_CallObject과 거의 유사하다고 생각하면 된다.
- python에서
- python이 class로 만들어졌다.
- import를 이용해서 Python 모듈를 호출하였다. 즉, random과 time이라는 모듈은 내가 만든 것이 아니다. Python을 설치하면 그냥 딸려오는 것이다. 이 말은 내가 호출하는 파이썬 파일 안에 다른 파이썬 모듈을 아무것이나 가져올 수 있다는 말이다. 얼마나 놀라운가!!! 파이썬이 확장되어 그 가능성이 무한대로 늘어난다. DB에 연결될 수 도 있고 network도 이루어질 수 있을 것이며 다른 여러가지와 합쳐져서 Python이 확대되어질 수 있을 것이다.
OpenGL/GLUT 함수를 파이썬에 호출하자(예제 중심)
C/C++ 코드는 전혀 손을 대지 않고 Python부분만을 수정함으로써 게임을 진행할 수 있다면 어떨까요? OpenGL에 사용되는 함수들을 Python에서 C/C++에서 사용하듯이 똑같이 사용한다면 스크립터인 Python만으로 게임을 만들수도 있지 않을까요?
OpenGL, 좀더 정확하게 말하면 GLUT를 Python에서 사용할 수 있도록 Extending(확장)시키면 C/C++에서는 Python을 딱 한번만 호출하고 나머지는 Python에서 다 처리하도록 할 수 있습니다. 재미있을 것 같지 않습니까?
참고로 이야기하면 앞서 두 예제는 Embedding에 관한 예제이다.
역시나 여기서 예제를 나열한다.
#include <windows.h>
#include <glglut.h>
#include 'Python.h'
PyObject *module, *func, *rc;
float g_Rx = 0, g_Ry = 0, g_Rz = 0;
void InitFakeGL(void);
void Python_Render()
{
rc = PyObject_CallObject(func, NULL );
if (rc == NULL) { PyErr_Print(); }
else {
//PyArg_Parse( rc, 'f', &g_Ry );
Py_DECREF(rc);
}
}
void RenderScene(void)
{
Python_Render();
}
void Idle()
{
Python_Render();
}
void ChangeSize(GLsizei w, GLsizei h)
{
glViewport( 0, 0, w, h);
float fAspect = (GLfloat)w/(GLfloat)h;
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective( 90, fAspect, 1.0f, 5000.0f );
}
void SetupRC(void)
{
glClearColor( 0.0f, 0.0f, 1.0f, 1.0f );
}
void main(int argc, char **argv)
{
glutInitDisplayMode(GLUT_DOUBLE|GLUT_RGB);
glutInitWindowSize( 640, 480);
glutCreateWindow('Embedding Python');
glutDisplayFunc(RenderScene);
glutReshapeFunc(ChangeSize);
SetupRC();
Py_Initialize();
PySys_SetArgv( argc, argv);
/* Add a static module */
InitFakeGL();
PyRun_SimpleString('print 'Embedding Python' ');
module = PyImport_ImportModule('fakegl');
if (module == NULL) { PyErr_Clear(); printf('Unable to import embed module
'); }
PyRun_SimpleString('print 'PyImport_ImportModule' ');
func = PyObject_GetAttrString(module, 'render');
if (func == NULL) { PyErr_Clear(); printf('Unable to bind to hello function in detect module
'); }
PyRun_SimpleString('print 'PyObject_GetAttrString' ');
glutMainLoop();
Py_Exit(0);
}
static PyObject *my_call_glRotatef(PyObject *self, PyObject *args)
{
float angle, x, y, z;
if (!PyArg_ParseTuple(args, 'ffff', &angle, &x, &y, &z)) return NULL;
glRotatef( angle, x, y, z);
Py_INCREF(Py_None);
return Py_None;
}
static PyObject *my_call_glTranslatef(PyObject *self, PyObject *args)
{
float x, y, z;
if (!PyArg_ParseTuple(args, 'fff', &x, &y, &z)) return NULL;
glTranslatef( x, y, z);
Py_INCREF(Py_None);
return Py_None;
}
static PyObject *my_call_glColor3f(PyObject *self, PyObject *args)
{
float r, g, b;
if (!PyArg_ParseTuple(args, 'fff', &r, &g, &b)) return NULL;
glColor3f( r, g, b);
Py_INCREF(Py_None);
return Py_None;
}
static PyObject *my_call_glVertex3f(PyObject *self, PyObject *args)
{
float x, y, z;
if (!PyArg_ParseTuple(args, 'fff', &x, &y, &z)) return NULL;
glVertex3f( x, y, z);
Py_INCREF(Py_None);
return Py_None;
}
static PyObject *my_call_glClear(PyObject *self, PyObject *args)
{
int mask;
if (!PyArg_ParseTuple(args, 'i', &mask)) return NULL;
glClear( mask );
Py_INCREF(Py_None);
return Py_None;
}
static PyObject *my_call_glMatrixMode(PyObject *self, PyObject *args)
{
int mode;
if (!PyArg_ParseTuple(args, 'i', &mode)) return NULL;
glMatrixMode( mode );
Py_INCREF(Py_None);
return Py_None;
}
static PyObject *my_call_glLoadIdentity(PyObject *self, PyObject *args)
{
if (!PyArg_ParseTuple(args, '')) return NULL;
glLoadIdentity();
Py_INCREF(Py_None);
return Py_None;
}
static PyObject *my_call_glBegin(PyObject *self, PyObject *args)
{
int n;
if (!PyArg_ParseTuple(args, 'i', &n)) return NULL;
glBegin( n );
Py_INCREF(Py_None);
return Py_None;
}
static PyObject *my_call_glEnd(PyObject *self, PyObject *args)
{
if (!PyArg_ParseTuple(args, '')) return NULL;
glEnd();
Py_INCREF(Py_None);
return Py_None;
}
static PyObject *my_call_glFlush(PyObject *self, PyObject *args)
{
if (!PyArg_ParseTuple(args, '')) return NULL;
glFlush();
Py_INCREF(Py_None);
return Py_None;
}
static PyObject *my_call_glutWireTeapot(PyObject *self, PyObject *args)
{
float f;
self = self;
if (!PyArg_ParseTuple(args, 'f', &f)) return NULL;
glutWireTeapot(f);
Py_INCREF(Py_None);
return Py_None;
}
static PyObject *my_call_glutSwapBuffers(PyObject *self, PyObject *args)
{
if (!PyArg_ParseTuple(args, '')) return NULL;
glutSwapBuffers();
Py_INCREF(Py_None);
return Py_None; }
static PyMethodDef my_c_fakeGL_methods[] = {
{'glTranslatef', my_call_glTranslatef, METH_VARARGS},
{'glRotatef', my_call_glRotatef, METH_VARARGS},
{'glColor3f', my_call_glColor3f, METH_VARARGS},
{'glVertex3f', my_call_glVertex3f, METH_VARARGS},
{'glClear', my_call_glClear, METH_VARARGS},
{'glMatrixMode', my_call_glMatrixMode, METH_VARARGS},
{'glLoadIdentity', my_call_glLoadIdentity, METH_VARARGS},
{'glBegin', my_call_glBegin, METH_VARARGS},
{'glEnd', my_call_glEnd, METH_VARARGS},
{'glFlush', my_call_glFlush, METH_VARARGS},
{'glutWireTeapot', my_call_glutWireTeapot, METH_VARARGS},
{'glutSwapBuffers', my_call_glutSwapBuffers, METH_VARARGS},
{NULL, NULL}
};
void InitFakeGL(void)
{
PyImport_AddModule('my_c_fakeGL');
Py_InitModule('my_c_fakeGL', my_c_fakeGL_methods);
}
fakegl.py
# --------------------------------------------------------
GL_COLOR_BUFFER_BIT = 0x00004000 #16384 # 0x00004000
# MatrixMode
GL_MODELVIEW = 0x1700
GL_PROJECTION = 0x1701
GL_TEXTURE = 0x1702
# BeginMode
GL_POINTS = 0x0000
GL_LINES = 0x0001
GL_LINE_LOOP = 0x0002
GL_LINE_STRIP = 0x0003
GL_TRIANGLES = 0x0004
GL_TRIANGLE_STRIP = 0x0005
GL_TRIANGLE_FAN = 0x0006
GL_QUADS = 0x0007
GL_QUAD_STRIP = 0x0008
GL_POLYGON = 0x0009
# --------------------------------------------------------
# 주의: OpenGL은 C함수이다. 가능하면 Python에서 C함수형태로 접근할 것
# Python은 들어쓰기가 중요한데...역시나 gl 과 glut에서 똑같이 중요하다.
from my_c_fakeGL import *
def glRender(Ry):
glClear(GL_COLOR_BUFFER_BIT)
glMatrixMode(GL_MODELVIEW)
glLoadIdentity()
glColor3f( 1, 0, 0 )
glTranslatef( 0, 0, -5 )
glRotatef(Ry, 0, 1, 0)
glutWireTeapot( 1 )
glColor3f( 1, 1, 1 )
glTranslatef( -15, 0, -5 )
glutWireTeapot( 1 )
glFlush()
glutSwapBuffers()
def render():
Ry = 0
count = 0
while Ry < 360:
glRender(Ry)
if Ry > 360 :
Ry = 0
print count
count = count + 1
Ry = Ry + 1
이 전의 예제들은 Python으로 만들어진 것을 C/C++에서 읽어들여서 실행시키는 것이었습니다. 이것은 'PyImport_ImportModule()' 함수에 의해서 이루어집니다. 이것을 'Python Embedding'이라고 합니다. 이번 예제는 그와 반대되는 부분도 등장합니다. 즉, C/C++에서 만든 함수를 Python에서 사용하고자합니다. 이것을 'Python Extending'이라고 합니다.
소개한 예제에서 가장 눈여보아야할 부분은 다음 부분입니다.
void InitFakeGL(void)
{
PyImport_AddModule('my_c_fakeGL');
Py_InitModule('my_c_fakeGL', my_c_fakeGL_methods);
}
static PyMethodDef my_c_fakeGL_methods[] = {
{'glTranslatef', my_call_glTranslatef, METH_VARARGS}
{NULL, NULL}
}
static PyObject *my_call_glTranslatef(PyObject *self, PyObject *args)
{
float x, y, z;
if (!PyArg_ParseTuple(args, 'fff', &x, &y, &z)) return NULL;
glTranslatef( x, y, z);
Py_INCREF(Py_None);
return Py_None;
}
C/C++ 부분을 살피면
- PyImport_AddModule로 모듈이름을 등록합니다. Python은 Java의 패키지와 비슷한 개념인 Module이라는 개념으로 부분들을 관리합니다.
- Py_InitModule 로 모듈 함수들을 등록한다.
- PyMethodDef 구조체 배열는 세 멤버가 한 쌍으로 구성되어지는데, '파이썬에서 사용할 이름', '함수 포인터' 와 '인수받는 형식' 으로 구성되어져있다. {NULL, NULL} 는 마지막임을 표시한다.
- Python과 연결되기 위한 '함수 포인터'는 static PyObject *my_call_glTranslatef(PyObject *self, PyObject *args)으로 형식으로 이루어져야 한다.
Python 부분을 살피면
C/C++에는 'render()'만을 호출했습니다. 하지만, python에서는 다른 함수인 'glRender()'를 만들어서 호출하고 있습니다. 또한 C/C++에서 python 모듈로 등록한 'my_c_fakeGL'을 불러다가 사용하고 있습니다. C/C++는 수정하지 않고, 단지 Python을 수정하는 것만으로도 프로그램에 변화를 가져옵니다.
___
참고
http://www.mcmillan-inc.com/embed.html
참고 자료
- C 확장 모듈 만들기 http://python.kwangwoon.ac.kr/pymoinmoin/moin.cgi/C_20_c8_ae_c0_e5_b8_f0_b5_e2_20_b8_b8_b5_e9_b1_e2
- 한글 파이썬 http://python.kwangwoon.ac.kr/pymoinmoin/moin.cgi/_c7_d1_b1_db_20_c6_c4_c0_cc_bd_e3
- 파이썬 공식 홈페이지 http://www.python.org
- 한국 파이썬 홈페이지 http://www.python.or.kr
- 한국 파이썬 사용자 모임 http://users.python.or.kr
- boost::python http://www.boost.org/libs/python/doc/
- PyTinker http://www.myevan.net/moniwiki/wiki.php/PyTinker