이것에 대한 더 많은 정보는 파이썬에 관한 책들에 있습니다: 프로그래밍 파이썬, 파이썬으로 인터넷 프로그래밍하기(Programming Python, Internet Programming with Python), 그리고 파이썬-책(Das Python-Buch) (독일어).
또한 파이썬 객체에 대한 고-수준 API도 있는데 이른바 '추상적(abstract)' 인터페이스에 의하여 제공됩니다 -- 더 자세한 사항은 Include/abstract.h를 읽어 보세요. 예를 들어 그것은 (PySequence_Length(), PySequence_GetItem(), 등등과 같은 호출을 사용하여) 어떠한 파이썬 연속열(예. 리스트와 터플)과의 접속도 허용할 뿐만 아니라 다른 많은 유용한 프로토콜과의 접속을 허용합니다.
PyObject *
PyObject_CallMethod(PyObject *object, char *method_name,
char *arg_format, ...);
이것은 -- 내장이든 혹은 사용자-정의이든 메쏘드를 가지고 있는 모든 객체에 작동합니다. 그 반환값의 참조횟수를 감소시키는(DECREF'ing) 것은 결국 여러분의 책임입니다.
예를 들어 한 파일 객체의 "seek" 메쏘드를 인수 10, 0 을 가지고 호출하려면 (그 파일 객체의 포인터가 "f"라는 가정하에):
res = PyObject_CallMethod(f, "seek", "(ii)", 10, 0);
if (res == NULL) {
... an exception occurred ...
}
else {
DECREF(res);
}
주목할 것은 PyObject_CallObject()가 항상 그 인수 목록에 대하여 터플을 원하므로, 함수를 인수없이 호출하려면, 그 형식에 "()"를 건네 주세요, 그리고 함수를 하나의 인수로 호출하려면, 그 인수를 괄호로 둘러싸세요, 다음과 같이 "(i)".
파이썬 코드에서는, "write()" 메쏘드를 지원하는 객체를 선언하세요. sys.stdout와 sys.stderr를 이 객체에 방향전환하세요. print_error를 호출하거나, 혹은 단순히 표준 역추적 메카니즘이 작동하도록 허용하세요. 그러면, 그 출력은 여러분의 write() 메쏘드가 그것을 보내는 곳에 출력될 것입니다.
이렇게 하는 가장 쉬운 방법은 표준 라이브러리에 있는 StringIO 클래스를 사용하는 것입니다.
표준 출력을 나포하기 위한 예제 코드와 사용법:
>>> class StdoutCatcher: ... def __init__(self): ... self.data = '' ... def write(self, stuff): ... self.data = self.data + stuff ... >>> import sys >>> sys.stdout = StdoutCatcher() >>> print 'foo' >>> print 'hello world!' >>> sys.stderr.write(sys.stdout.data) foo hello world!
module = PyImport_ImportModule("<modulename>");
만약 그 모듈이 아직 수입되지 않았다면 (즉. sys.modules에 아직 존재하지 않는다면), 이것은 그 모듈을 초기화합니다; 그렇지 않으면 단순히 sys.modules["<modulename>"]의 그 값을 반환합니다.
주목할 것은 그 모듈을 어떠한 이름공간에도 집어 넣지 않는다는 것입니다 -- 오직 초기화 되었는지 그리고 sys.modules에 저장되었는지 만을 확인합니다.
그러면 그 모듈의 속성에 (즉. 그 모듈에 정의된 어떤 이름에도) 다음과 같이 접근할 수 있습니다:
attr = PyObject_GetAttrString(module, "<attrname>");
변수들을 그 모듈에 할당하기 위하여, PyObject_SetAttrString()을 호출하는 것 또한 작동합니다.
유용한 자동화된 접근법은 SWIG입니다 (C에도 작동합니다): http://www.swig.org//.
다음 라인을 지우고:
#include "allobjects.h" #include "modsupport.h"대신에 다음을 삽입하세요:
#include "Python.h"다음과 같이 추가할 필요도 있습니다.
#include "rename2.h"
만약 그 모듈이 "old names"을 사용하면.
이것은 다른 오래된 파이썬 모듈에도 일어날 수 있는데, 같은 해결책이 적용됩니다.
모든 모듈의 초기화 함수는 다음과 비슷한 라인을 가질 것입니다:
module = Py_InitModule("yourmodule", yourmodule_functions);
만약 이 함수에 건네지는 문자열이 여러분의 확장 모듈 이름과 같지 않다면, SystemError가 일어날 것입니다.
파이썬에서는 codeop 모듈을 사용할 수 있는데, 해석기의 행위를 거의 근접하게 흉내냅니다. 예를 들어, IDLE은 이것을 사용합니다.
C에서 그렇게 하기위한 가장 쉬운 방법은 PyRun_InteractiveLoop()를 호출하고 (아마도 개별적인 쓰레드로) 그리고 파이썬 인터프리터가 그 입력을 여러분을 대신하여 처리하도록 놓아 두는 것입니다. 또한 PyOS_ReadlineFunctionPointer를 설정하여 자신이 재단한 입력 함수를 지적할 수도 있습니다. 더 힌트를 원하시면 Modules/readline.c와 Parser/myreadline.c를 참조하세요.
그렇지만 때로 내장된 파이썬 인터프리터를 여러분의 나머지 어플리케이션과 같은 쓰레드에서 실행할 필요가 있지만, 사용자 입력을 기다리는 중이어서 PyRun_InteractiveLoop()를 중지 시킬수 없는 때가 있습니다. 그러면 하나의 해결책은 PyParser_ParseString()를 호출해서 e.error가 E_EOF와 같은지 테스트하는 것입니다 (이때 그 입력은 미완성입니다). 다음은 알렉스 파버(Alex Farber)의 코드에 영감을 받은, 검증되지 않은, 예제 코드 조각입니다:
#include <Python.h> #include <node.h> #include <errcode.h> #include <grammar.h> #include <parsetok.h> #include <compile.h>
int testcomplete(char *code)
/* code should end in \n */
/* return -1 for error, 0 for incomplete, 1 for complete */
{
node *n;
perrdetail e;
n = PyParser_ParseString(code, &_PyParser_Grammar,
Py_file_input, &e);
if (n == NULL) {
if (e.error == E_EOF)
return 0;
return -1;
}
PyNode_Free(n);
return 1;
}
또 다른 해결책은 그 접수된 문자열을 Py_CompileString()으로 컴파일 해보는 것입니다. 만약 잘 컴파일 된다면 - 그 반환된 코드 객체를 PyEval_EvalCode()를 호출함으로써 실행해 보세요. 그렇지 않으면 나중에 사용하기 위하여 그 입력을 저장하세요. 만약 컴파일이 실패하면, 그것이 에러인지 혹은 단지 더 입력이 필요한 것인지 알아 보세요 - 그 예외 터플로부터 메시지 문자열을 추출하여 그것을 "해석중에 예상 못한 EOF(unexpected EOF while parsing)"과 비교해 보시면 됩니다. 여기에 GNU readline 라이브러리를 사용한 완전한 예제가 있습니다. (readline()호출하는 중에 SIGINT를 무시하고 싶을 수도 있습니다):
#include <stdio.h> #include <readline.h>
#include <Python.h> #include <object.h> #include <compile.h> #include <eval.h>
int main (int argc, char* argv[])
{
int i, j, done = 0; /* lengths of line, code */
char ps1[] = ">>> ";
char ps2[] = "... ";
char *prompt = ps1;
char *msg, *line, *code = NULL;
PyObject *src, *glb, *loc;
PyObject *exc, *val, *trb, *obj, *dum;
Py_Initialize ();
loc = PyDict_New ();
glb = PyDict_New ();
PyDict_SetItemString (glb, "__builtins__", PyEval_GetBuiltins ());
while (!done)
{
line = readline (prompt);
if (NULL == line) /* CTRL-D pressed */
{
done = 1;
}
else
{
i = strlen (line);
if (i > 0)
add_history (line); /* save non-empty lines */
if (NULL == code) /* nothing in code yet */
j = 0;
else
j = strlen (code);
code = realloc (code, i + j + 2);
if (NULL == code) /* out of memory */
exit (1);
if (0 == j) /* code was empty, so */
code[0] = '\0'; /* keep strncat happy */
strncat (code, line, i); /* append line to code */
code[i + j] = '\n'; /* append '\n' to code */
code[i + j + 1] = '\0';
src = Py_CompileString (code, "<stdin>", Py_single_input);
if (NULL != src) /* compiled just fine - */
{
if (ps1 == prompt || /* ">>> " or */
'\n' == code[i + j - 1]) /* "... " and double '\n' */
{ /* so execute it */
dum = PyEval_EvalCode ((PyCodeObject *)src, glb, loc);
Py_XDECREF (dum);
Py_XDECREF (src);
free (code);
code = NULL;
if (PyErr_Occurred ())
PyErr_Print ();
prompt = ps1;
}
} /* syntax error or E_EOF? */
else if (PyErr_ExceptionMatches (PyExc_SyntaxError))
{
PyErr_Fetch (&exc, &val, &trb); /* clears exception! */
if (PyArg_ParseTuple (val, "sO", &msg, &obj) &&
!strcmp (msg, "unexpected EOF while parsing")) /* E_EOF */
{
Py_XDECREF (exc);
Py_XDECREF (val);
Py_XDECREF (trb);
prompt = ps2;
}
else /* some other syntax error */
{
PyErr_Restore (exc, val, trb);
PyErr_Print ();
free (code);
code = NULL;
prompt = ps1;
}
}
else /* some non-syntax error */
{
PyErr_Print ();
free (code);
code = NULL;
prompt = ps1;
}
free (line);
}
}
Py_XDECREF(glb);
Py_XDECREF(loc);
Py_Finalize();
exit(0);
}
.gdbinit 파일에서 (혹은 상호대화적으로), 명령어를 추가하세요
br _PyImport_LoadDynamicModule
$ gdb /local/bin/python
gdb) run myscript.py
gdb) continue # repeat until your extension is loaded
gdb) finish # so that your extension is loaded
gdb) br myfunction.c:50
gdb) continue
그렇지만, 자바와 마찬가지로, 파이썬은 제일-클래스(first-class) 객체와 제이-클래스(second-class) 객체가 있다고 주장합니다 (전자는 형이고, 후자는 클래스입니다), 그리고 그 두 쌍동이는 절대로 만나지 않을 것입니다[아마도].
그렇지만, 라이브러리는 더 일반적으로 요망되는 객체들을 위한 클래스 포장자를 훌륭하게 제공하여 왔으며 (예제를 보시려면 UserDict, UserList 그리고 UserString을 참조하세요), 그리고 여러분이 혹시나 코드를 작성하고 싶은 기분이 든다면 언제나 환영하고 있습니다.