Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Extending and Embedding Python

Extending and Embedding Python

Abc432bb0450574a25b15ff23d399d5a?s=128

Vladimir Pouzanov

January 30, 2010
Tweet

Transcript

  1. Extending and Embedding Python Âëàäèìèð Ïóçàíîâ farcaller@hackndev.com Âëàäèìèð Êèðèëëîâ proger@hackndev.com

    Hack&Dev Team
  2. CPython (Stackless) Jython IronPython Java DLR CLR C C++ CPython

    API Pyrex/ Cython SWIG boost SIP Objective-C Java VM .NET
  3. Èíòåðïðåòàòîðû

  4. CPython Îñîáåííîñòè ðàçðàáàòûâàåòñÿ Python Software Foundation êëàññè÷åñêàÿ ðåàëèçàöèÿ, èñïîëçóåòñÿ ïî÷òè

    ïîâñþäó ðåàëèçîâàí íà Ñè êàê èíòåðïðåòàòîð áàéòêîäà åäèíñòâåííûé ðåàëèçóåò âåñü ôóíêöèîíàë Python ëèöåíçèÿ: GPL 2 Íåäîñòàòêè GIL  Global Interpreter Lock
  5. CPython-stackless Ïîäâèä CPython, Stackless ââîäèò â Python ïëàíèðîâùèê ìèêðîïîòîêîâ 

    äåøåâûõ è ëåãêèõ. Ýòî ïîçâîëÿåò óëó÷øèòü ñòðóêòóðó êîäà ñäåëàòü åãî áîëåå ÷èòàåìûì óâåëè÷èòü ïðîäóêòèâíîñòü ïðîãðàììèñòà Îñíîâíûå îòëè÷èÿ Ìèêðîïîòîêè  òàñêëåòû Òàñêëåòû ïðåäñòàâëÿþò ñîáîé îáåðòêè âîêðóã ôóíêöèé äëÿ èõ çàïóñêà êàê â âèäå ìèêðîïîòîêîâ Êàíàëû Êàíàëû èñïîëüçóþòñÿ äëÿ äâóñòîðîííåé ñâÿçè ìåæäó òàñêëåòàìè Ïëàíèðîâùèê Êàðóñåëüíûé ïëàíèðîâùèê ïîçâîëÿåò ïëàíèðîâàòü òàñêëåòû êàê êîîïåðàòèâíî, òàê è âûãðóæàåìî Ñåðèàëèçàöèÿ Òàñêëåòû ìîæíî ñåðèàëèçîâàòü (÷åðåç pickle) íà äèñê, äëÿ èõ äàëüíåéøåãî âîçîáíîâëåíèÿ
  6. 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 object at 0x00A45B30> >>> stackless.tasklet(sending_tasklet)() <stackless.tasklet object at 0x00A45B70> >>> stackless.tasklet(another_tasklet)() <stackless.tasklet object at 0x00A45BF0> >>> stackless.run() Recieving tasklet started Sending tasklet started send from sending_tasklet Receiving tasklet finished Just another tasklet in the scheduler sending tasklet finished
  7. Jython Ïîëíîöåííàÿ ðåàëèçàöèÿ èíòåðïðåòàòîðà Python íà áàçå Java VM. Äèíàìè÷åñêàÿ

    êîìïèëÿöèÿ â Java-áàéòêîä  ìàêñèìàëüíàÿ ïðîèçâîäèòåëüíîñòü ïðè ñîõðàíåíèè èíòåðàêòèâíîñòè âîçìîæíîñòü ðàñøèðåíèÿ Javaêëàññîâ ïîçâîëÿåò ýôôåêòèâíî èñïîëüçîâàòü àáñòðàêòíûå êëàññû îïöèîíàëüíàÿ ñòàòè÷åñêàÿ êîìïèëÿöèÿ  âîçìîæíîñòü èñïîëüçîâàíèÿ â ñåðâëåòàõ, àïïëåòàõ, è ò.ä. ñèíòàêñèñ Python îáúåäèíÿåò ïîðàçèòåëüíóþ ìîùü ñ ïðîñòûì ñèíòàêñèñîì; ïîëíîâåñíàÿ îáúåêòíàÿ ìîäåëü îòëè÷íî âïèñûâàåòñÿ â äèçàéí ÎÎÏ Java.
  8. IronPython ðåàëèçàöèÿ Python äëÿ CLR (Common Language Runtime) ñ èñïîëüçîâàíèåì

    ìàøèíû .NET èíòåãðàöèÿ ñ òåõíîëîãèÿìè òèïà MS Silverlight ðàçðàáàòûâàåòñÿ Microsoft ëèöåíçèÿ: MSPL ÷àñòè÷íî ïîääåðæèâàåòñÿ Mono
  9. Ðàñøèðåíèå

  10. ìîäóëè íà C Èñïîëüçóåòñÿ Python API ñïîñîá âçàèìîäåéñòâèÿ ñ èíòåðïðåòàòîðîì

    íàïðÿìóþ âñ¼ áðåìÿ óïðàâëåíèÿ Python-îáúåêòàìè ïàäàåò íà ïðîãðàììèñòà áîëüøå âîçìîæíîñòåé äîñòóïà âî ¾âíåøíèé ìèð¿
  11. 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); }
  12. 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); }
  13. 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); }
  14. Ñáîðêà .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 $@
  15. ctypes âñòðîåííûé â Python ìîäóëü äëÿ äîñòóïà ê C-ôóíêöèÿì âî

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

    äàííûõ êàê Python, òàê è C òðàíñëèðóåò êîä â C-ìîäóëü cython ïðîäîëæåíèå ïðîåêòà pyrex áûñòðûé ïîääåðæêà íåêîòîðûõ âîçìîæíîñòåé Ñ++
  18. 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 = <char **>PyMem_Malloc(argc * sizeof(char *)) for i from 0 <= i < argc: arg = sys.argv[i] arg_len = len(sys.argv[i]) argv[i] = <char *>PyMem_Malloc(arg_len + 1) memcpy(argv[i], arg, arg_len + 1) elm_init(argc, argv) include "elementary.c_elementary_object.pxi" # ...
  19. None
  20. 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();
  21. 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)
  22. boost::python  ïðèìåð BOOST_PYTHON_MODULE(libboopyclass) { boost::python::class_<World>("World") .def("greet", &World::greet) .def("set", &World::set);

    boost::python::class_<PlusOne>("PlusOne") .def("func", &PlusOne::func); boost::python::class_<Var>("Var", boost::python::init<std::string>()) .def_readonly("name", &Var::name) .def_readwrite("value", &Var::value); boost::python::class_<Num>("Num") .add_property("rovalue", &Num::get) .add_property("value", &Num::get, &Num::set); boost::python::class_<BaseWrap1, boost::noncopyable>("Base1") .def("f", boost::python::pure_virtual(&Base1::f)); boost::python::class_<BaseWrap2, boost::noncopyable>("Base2") .def("f", &Base2::f, &BaseWrap2::default_f); }
  23. Èíúåêöèÿ è èññëåäîâàíèå â êîä íà C/C++ ñ äîñòóïîì ê

    C-ôóíêöèÿì èç âíåøíèõ áèáëèîòåê (ctypes, API) hacking! â êîä íà Java (jython) â êîä íà C# (ironpython) â êîä íà Objective-C ñ ïîëíûì äîñòóïîì ê îáúåêòíîìó ðàíòàéìó (pyobjc)
  24. pyobjc Áèíäèíãè íà Objective-C ïîçâîëÿþò ïîëó÷èòü ïîëíûé äîñòóï ê òåêóùåìó

    îêðóæåíèþ ðàíòàéìà èç Python, êóäà áóäóò îòîáðàæåíû âñå ñóùåñòâóþùèå êëàññû. Äîñòóï êî âñåì îñíîâíûì ôðåéìâîðêàì íà OSX/iPhoneOS âîçìîæíîñòü íàïèñàíèÿ ïîëíîôóíêöèîíàëüíûõ ïðîãðàìì èñïîëüçóÿ òîëüêî Python èññëåäîâàíèå objcðàíòàéìà â äðóãèõ ïðîöåññàõ
  25. >>> app = NSApplication.sharedApplication() >>> print app.windows() ( "<BrowserWindow: 0x11546a030>",

    "<NSPanel: 0x11543a110>", "<MHOSuggestionWindow: 0x11543de60>", "<NSPanel: 0x1154648a0>", "<NSPanel: 0x115435ad0>", "<NSWindow: 0x115c4d5e0>", "<NSWindow: 0x11f188f40>", "<FSObjectBrowser: 0x11f18afd0>", "<WebTextInputPanel: 0x11f5bbee0>", "<NSWindow: 0x11ef6b7e0>" ) >>> win = app.windows()[0] >>> controller = win.delegate() >>> doc = controller.document() >>> print controller, doc <BrowserWindowController: 0x11545c560> <BrowserDocument: 0x115c6a790> >>> 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!"')
  26. None
  27. Cïàñèáî çà âíèìàíèå! Âîïðîñû?