Slide 1

Slide 1 text

Extending and Embedding Python Âëàäèìèð Ïóçàíîâ [email protected] Âëàäèìèð Êèðèëëîâ [email protected] Hack&Dev Team

Slide 2

Slide 2 text

CPython (Stackless) Jython IronPython Java DLR CLR C C++ CPython API Pyrex/ Cython SWIG boost SIP Objective-C Java VM .NET

Slide 3

Slide 3 text

Èíòåðïðåòàòîðû

Slide 4

Slide 4 text

CPython Îñîáåííîñòè ðàçðàáàòûâàåòñÿ Python Software Foundation êëàññè÷åñêàÿ ðåàëèçàöèÿ, èñïîëçóåòñÿ ïî÷òè ïîâñþäó ðåàëèçîâàí íà Ñè êàê èíòåðïðåòàòîð áàéòêîäà åäèíñòâåííûé ðåàëèçóåò âåñü ôóíêöèîíàë Python ëèöåíçèÿ: GPL 2 Íåäîñòàòêè GIL  Global Interpreter Lock

Slide 5

Slide 5 text

CPython-stackless Ïîäâèä CPython, Stackless ââîäèò â Python ïëàíèðîâùèê ìèêðîïîòîêîâ  äåøåâûõ è ëåãêèõ. Ýòî ïîçâîëÿåò óëó÷øèòü ñòðóêòóðó êîäà ñäåëàòü åãî áîëåå ÷èòàåìûì óâåëè÷èòü ïðîäóêòèâíîñòü ïðîãðàììèñòà Îñíîâíûå îòëè÷èÿ Ìèêðîïîòîêè  òàñêëåòû Òàñêëåòû ïðåäñòàâëÿþò ñîáîé îáåðòêè âîêðóã ôóíêöèé äëÿ èõ çàïóñêà êàê â âèäå ìèêðîïîòîêîâ Êàíàëû Êàíàëû èñïîëüçóþòñÿ äëÿ äâóñòîðîííåé ñâÿçè ìåæäó òàñêëåòàìè Ïëàíèðîâùèê Êàðóñåëüíûé ïëàíèðîâùèê ïîçâîëÿåò ïëàíèðîâàòü òàñêëåòû êàê êîîïåðàòèâíî, òàê è âûãðóæàåìî Ñåðèàëèçàöèÿ Òàñêëåòû ìîæíî ñåðèàëèçîâàòü (÷åðåç pickle) íà äèñê, äëÿ èõ äàëüíåéøåãî âîçîáíîâëåíèÿ

Slide 6

Slide 6 text

CPython-stackless  ïðèìåð >>> import stackless >>> channel = stackless.channel() >>> def receiving_tasklet(): ... print "Recieving tasklet started" ... print channel.receive() ... print "Receiving tasklet finished" ... >>> def sending_tasklet(): ... print "Sending tasklet started" ... channel.send("send from sending_tasklet") ... print "sending tasklet finished" ... >>> def another_tasklet(): ... print "Just another tasklet in the scheduler" ... >>> stackless.tasklet(receiving_tasklet)() >>> stackless.tasklet(sending_tasklet)() >>> stackless.tasklet(another_tasklet)() >>> stackless.run() Recieving tasklet started Sending tasklet started send from sending_tasklet Receiving tasklet finished Just another tasklet in the scheduler sending tasklet finished

Slide 7

Slide 7 text

Jython Ïîëíîöåííàÿ ðåàëèçàöèÿ èíòåðïðåòàòîðà Python íà áàçå Java VM. Äèíàìè÷åñêàÿ êîìïèëÿöèÿ â Java-áàéòêîä  ìàêñèìàëüíàÿ ïðîèçâîäèòåëüíîñòü ïðè ñîõðàíåíèè èíòåðàêòèâíîñòè âîçìîæíîñòü ðàñøèðåíèÿ Javaêëàññîâ ïîçâîëÿåò ýôôåêòèâíî èñïîëüçîâàòü àáñòðàêòíûå êëàññû îïöèîíàëüíàÿ ñòàòè÷åñêàÿ êîìïèëÿöèÿ  âîçìîæíîñòü èñïîëüçîâàíèÿ â ñåðâëåòàõ, àïïëåòàõ, è ò.ä. ñèíòàêñèñ Python îáúåäèíÿåò ïîðàçèòåëüíóþ ìîùü ñ ïðîñòûì ñèíòàêñèñîì; ïîëíîâåñíàÿ îáúåêòíàÿ ìîäåëü îòëè÷íî âïèñûâàåòñÿ â äèçàéí ÎÎÏ Java.

Slide 8

Slide 8 text

IronPython ðåàëèçàöèÿ Python äëÿ CLR (Common Language Runtime) ñ èñïîëüçîâàíèåì ìàøèíû .NET èíòåãðàöèÿ ñ òåõíîëîãèÿìè òèïà MS Silverlight ðàçðàáàòûâàåòñÿ Microsoft ëèöåíçèÿ: MSPL ÷àñòè÷íî ïîääåðæèâàåòñÿ Mono

Slide 9

Slide 9 text

Ðàñøèðåíèå

Slide 10

Slide 10 text

ìîäóëè íà C Èñïîëüçóåòñÿ Python API ñïîñîá âçàèìîäåéñòâèÿ ñ èíòåðïðåòàòîðîì íàïðÿìóþ âñ¼ áðåìÿ óïðàâëåíèÿ Python-îáúåêòàìè ïàäàåò íà ïðîãðàììèñòà áîëüøå âîçìîæíîñòåé äîñòóïà âî ¾âíåøíèé ìèð¿

Slide 11

Slide 11 text

static PyMethodDef ifconfig_methods[] = { /* ... */ { "ieee80211_status", ifconfig_ieee80211_status, METH_VARARGS, "ieee80211_status(ifname)\n" }, { "setifaddr", (PyCFunction)setifaddr, METH_VARARGS | METH_KEYWORDS, "setifaddr(ifname, addr, netmask='', broadcast='',\n" " dst='', alias=False, delete=False)\n\n" "Set the given address addr to interface ifname.\n" "Only AF_INET family is supported at the moment.\n\n" "broadcast and dst are exclusive (the same)\n" }, {NULL, NULL, NULL, NULL}, }; PyMODINIT_FUNC initifconfig(void) { Py_InitModule("ifconfig", ifconfig_methods); }

Slide 12

Slide 12 text

static PyObject * ifconfig_ieee80211_status(PyObject *self, PyObject *args) { PyObject *status; char *ifname; struct ieee80211_nwid nwid; if (PyArg_ParseTuple(args, "s", &ifname) == NULL) return (NULL); if ((status = PyDict_New()) == NULL) return (PyErr_NoMemory()); /* nwid */ memset(&ifr, 0, sizeof(ifr)); ifr.ifr_data = (caddr_t)&nwid; strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); inwid = ioctl(s, SIOCG80211NWID, (caddr_t)&ifr); if (inwid == 0) { /* nwid.i_nwid is not NULL terminated. */ obj = PyString_FromStringAndSize(nwid.i_nwid, nwid.i_len > IEEE80211_NWID_LEN ? IEEE80211_NWID_LEN : nwid.i_len); PyDict_SetItemString(status, "nwid", obj); Py_XDECREF(obj); } /* ... */ return (status); }

Slide 13

Slide 13 text

static PyObject * ifconfig_ifstatus(PyObject *self, PyObject *args) { int s; struct ifreq *ifr; PyObject *mediadict, *inetlist, *status; /* description */ bzero(ifr, sizeof(*ifr)); strlcpy(ifr->ifr_name, ifname, sizeof(ifr->ifr_name)); ifr->ifr_data = (caddr_t)&ifdescr; ioctl(s, SIOCGIFDESCR, (caddr_t)ifr); obj = PyString_FromString(ifdescr); PyDict_SetItemString(status, "description", obj); Py_XDECREF(obj); return (status); postifaddrserror: postmediaerror: Py_XDECREF(mediadict); error: Py_XDECREF(inetlist); Py_XDECREF(status); free(ifr); close(s); PyErr_SetFromErrno(PyExc_OSError); return (NULL); }

Slide 14

Slide 14 text

Ñáîðêà .include "../Makefile.inc" .MAIN: build .SUFFIXES: .c .so NET= __init__.py autoconf.py ifconfig.so interface.py var.py DEBUG= -g -DDEBUG CPPFLAGS= -I/usr/local/include -I/usr/local/include/python2.6 LDFLAGS= -L/usr/local/lib -L/usr/local/lib/python2.6 build: ${NET} .c.so: cc ${DEBUG} -fPIC -shared ${CPPFLAGS} ${LDFLAGS} \ $< -o $@

Slide 15

Slide 15 text

ctypes âñòðîåííûé â Python ìîäóëü äëÿ äîñòóïà ê C-ôóíêöèÿì âî âíåøíèõ áèáëèîòåêàõ. Ïðåäîñòàâëÿåò òèïû õðàíåíèÿ, ñîâìåñòèìûå ñ C. Ìîæíî èñïîëüçîâàòü äëÿ ãåíåðàöèè èíòåðôåéñîâ ê áèáëèîòåêàì íà C ñ ïîìîùüþ Python-only êîäà.

Slide 16

Slide 16 text

No content

Slide 17

Slide 17 text

pyrex/cython pyrex ïîçâîëÿåò ïèñàòü ñìåøàííûé C/Python ïñåâäîêîä ìîæíî èñïîëüçîâàòü òèïû äàííûõ êàê Python, òàê è C òðàíñëèðóåò êîä â C-ìîäóëü cython ïðîäîëæåíèå ïðîåêòà pyrex áûñòðûé ïîääåðæêà íåêîòîðûõ âîçìîæíîñòåé Ñ++

Slide 18

Slide 18 text

pyrex/cython  ïðèìåð import sys import evas.c_evas cimport evas.c_evas as c_evas cimport evas.python import traceback def init(): cdef int argc, i, arg_len cdef char **argv, *arg argc_orig = argc = len(sys.argv) argv = PyMem_Malloc(argc * sizeof(char *)) for i from 0 <= i < argc: arg = sys.argv[i] arg_len = len(sys.argv[i]) argv[i] = PyMem_Malloc(arg_len + 1) memcpy(argv[i], arg, arg_len + 1) elm_init(argc, argv) include "elementary.c_elementary_object.pxi" # ...

Slide 19

Slide 19 text

No content

Slide 20

Slide 20 text

swig Èíñòðóìåíò äëÿ ãåíåðàöèè áèíäèíãîâ C/C++ êîäà íà ñêðèïòîâûå ÿçûêè: Perl, PHP, Python, Tcl, Ruby. Îòëè÷íî ïîäõîäèò äëÿ òåñòèðîâàíèÿ è ïðîòîòèïèðîâàíèÿ êîäà. /* example.i */ %module example %{ /* Put header files here or function declarations like below */ extern double My_variable; extern int fact(int n); extern int my_mod(int x, int y); extern char *get_time(); %} extern double My_variable; extern int fact(int n); extern int my_mod(int x, int y); extern char *get_time();

Slide 21

Slide 21 text

boost::python, SIP boost::python (http://www.boost.org) ïîçâîëÿåò ýôôåêòèâíî âçàèìîäåéñòâîâàòü ñ Python èç êîäà íà C++ ïîääåðæêà ññûëîê è óêàçàòåëåé ðåãèñòðàöèÿ ïðèâåäåíèÿ òèïîâ àâòîìàòè÷åñêèå êðîññìîäóëüíûå ïðèâåäåíèÿ òèïîâ ýôôåêòèâíàÿ ïåðåãðóçêà ôóíêöèé òðàíñëÿöèÿ èñêëþ÷åíèé èç C++ â Python àðãóìåíòûêëþ÷è è àðãóìåíòû ïî óìîë÷àíèþ ìàíèïóëÿöèÿ îáúåêòàìè Python èç C++ àâòîìàòè÷åñêèé ýêñïîðò èòåðàòîðîâ C++ â èòåðàòîðû Python ýôôåêòèâåí äëÿ âñòðàèâàíèÿ èíòåðïðåòàòîðà â êîä SIP îòíîñèòåëüíî ëåãêèå è áûñòðûå ìåòîäû ñîçäàòü îáåðòêè êîäà C++ äëÿ Python ñèíòàêñè÷åñêè ïîõîæ íà swig success story: Qt (PyQt)

Slide 22

Slide 22 text

boost::python  ïðèìåð BOOST_PYTHON_MODULE(libboopyclass) { boost::python::class_("World") .def("greet", &World::greet) .def("set", &World::set); boost::python::class_("PlusOne") .def("func", &PlusOne::func); boost::python::class_("Var", boost::python::init()) .def_readonly("name", &Var::name) .def_readwrite("value", &Var::value); boost::python::class_("Num") .add_property("rovalue", &Num::get) .add_property("value", &Num::get, &Num::set); boost::python::class_("Base1") .def("f", boost::python::pure_virtual(&Base1::f)); boost::python::class_("Base2") .def("f", &Base2::f, &BaseWrap2::default_f); }

Slide 23

Slide 23 text

Èíúåêöèÿ è èññëåäîâàíèå â êîä íà C/C++ ñ äîñòóïîì ê C-ôóíêöèÿì èç âíåøíèõ áèáëèîòåê (ctypes, API) hacking! â êîä íà Java (jython) â êîä íà C# (ironpython) â êîä íà Objective-C ñ ïîëíûì äîñòóïîì ê îáúåêòíîìó ðàíòàéìó (pyobjc)

Slide 24

Slide 24 text

pyobjc Áèíäèíãè íà Objective-C ïîçâîëÿþò ïîëó÷èòü ïîëíûé äîñòóï ê òåêóùåìó îêðóæåíèþ ðàíòàéìà èç Python, êóäà áóäóò îòîáðàæåíû âñå ñóùåñòâóþùèå êëàññû. Äîñòóï êî âñåì îñíîâíûì ôðåéìâîðêàì íà OSX/iPhoneOS âîçìîæíîñòü íàïèñàíèÿ ïîëíîôóíêöèîíàëüíûõ ïðîãðàìì èñïîëüçóÿ òîëüêî Python èññëåäîâàíèå objcðàíòàéìà â äðóãèõ ïðîöåññàõ

Slide 25

Slide 25 text

>>> app = NSApplication.sharedApplication() >>> print app.windows() ( "", "", "", "", "", "", "", "", "", "" ) >>> win = app.windows()[0] >>> controller = win.delegate() >>> doc = controller.document() >>> print controller, doc >>> frame = doc._selectedFrameView() >>> webView = frame._webView() >>> evl = lambda x: webView.stringByEvaluatingJavaScriptFromString_(x) >>> evl('alert("Double bridged string ^_^")') >>> evl('document.getElementsByClassName("pageheading")[0].innerHTML = "Python was here!"')

Slide 26

Slide 26 text

No content

Slide 27

Slide 27 text

Cïàñèáî çà âíèìàíèå! Âîïðîñû?