ÀÌ°Í¿¡ ´ëÇÑ ´õ ¸¹Àº Á¤º¸´Â ÆÄÀ̽㿡 °üÇÑ Ã¥µé¿¡ ÀÖ½À´Ï´Ù: ÇÁ·Î±×·¡¹Ö ÆÄÀ̽ã, ÆÄÀ̽ãÀ¸·Î ÀÎÅÍ³Ý ÇÁ·Î±×·¡¹ÖÇϱâ(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À» ÂüÁ¶Çϼ¼¿ä), ±×¸®°í ¿©·¯ºÐÀÌ È¤½Ã³ª Äڵ带 ÀÛ¼ºÇÏ°í ½ÍÀº ±âºÐÀÌ µç´Ù¸é ¾ðÁ¦³ª ȯ¿µÇÏ°í ÀÖ½À´Ï´Ù.