Jak vytváříte c++ moduly pro Python ? rubrika: Programování: Python
zdar lidi,
Moc se tu nemluví o Pythonu, tak zkusím něco nakousnout.
Potřebuji vytvořit c++ rozšíření pro Python, abych zapouzdřil a zpřístupnil jednu c++ knihovnu. Zjistil jsem, že jestvuje několik řešení a každé na to jde jiným způsobem.
Rád bych se zeptal, co používáte a jak se vám to osvědčilo na větších projektech. A těm, kdo budou hledat jako já snad pomůže pár mých poznámek :-)
Já jsem poctivě hledal a studoval a tady je má zkušenost.
Z počátku jsem si neuvědomil, že je potřeba rozlišit dvě věci:
- Buď máte C++ kód, třeba nějakou knihovnu, nebo vlastní kód a ten potřebujete dostat do Pythonu - můj případ
- Nebo máte nějaký kód v Pythonu, který je pomalý a proto jej chcete dostat přes C/C++ do zkompilovaného modulu.
Našel jsem tyto možnosti:
1) Přímo Python API dle dokumentace http://docs.python.org/py3k/c-api/ - do hloubky jsem nezkoumal, jsou o tom i dva články na root.cz, ten aktuálnější od Michala Hořejška je zde http://www.root.cz/clanky/vytvarime-v-c-cpp-modul-pro-python/. Mám pocit, že to je C řešení, které se na C++ příliš nehodí. Poměrně mnoho psaní a kombinování C a C++, přišlo mi to nepřehledné.
2) Cython - tento projekt překládá kód pythonu do C++. Umí přeložit přímo kód Python, nebo můžete použít rozšířenou syntaxi, která řeší některé věci chybějící v Pythonu (například určíte datové typy proměných). Umí importovat C++ knihovny, ale je s tím dost psaní, vlastně je potřeba opsat hlavičkový soubor určitým způsobem. Podobný projekt je Pyrex, ze kterého Cython vychází.
3) Shed Skin http://www.osnews.com/story/11984 - kompiluje Python do C++. Jestli jsem to dobře pochopil, tak neumožňuje importovat jiný C++ kód, ale jste odkázání na Python a to ještě s určitými omezeními. Ale odměnou by měla být efektivní výsledný C++ kód a tím i rychlý modul pythonu. Může se hodit, když máte nějaký náročný, pomalý kód v Pythonu. Pomocí Shed Skinu by měl jít přímo přeložit do modulu. Nezkoumal jsem do hloubky, protože já potřeboval něco jiného, ale ještě se k tomu někdy vrátím.
3) Swig http://www.swig.org/ - pracuje přímo s C++ kódem. Ze zdrojového kódu C++ (nějaké knihovna, vlastní kód) vytvoří jiný zdrojový kód C++, který po zkompilování sestaví modul. Je to rozsáhlý projekt, který podporuje mnoho dalších jazyků, včetně třeba PHP. Stojí za prostudování.
4)Boost.Python http://www.boost.org/doc/libs/1_51_0/libs/python/doc/index.html součást poměrně rozsáhlé C++ knihovny. Z počátku se mi to zdálo strašně složité, nebyl jsem to pochopit základní věci. Pak jsem zjistil, že nemusím používat jejich nástroj pro kompilaci - bjam, ale že mohu kompilovat přímo pomocí g++. Tedy, bjam je takové lepší make a nebude špatná věc, ale nerozuměli jsme si. Nejspíš jsem něco popletl, takže Vás od bjamu nechci odrazovat, tvůrci knihovny boost jej doporučují.
Maje C++ kód, který jsem chtěl dostat do Pythonu, nemohl jsem použít Shed Skin a použití Cythonu asi také není úplně vhodné. Shed Skin i Cython však zkusím použít, až budu potřebovat zrychlit něco, co mám napsané v Pythonu a převést pomalé části kódu do C++ a do zkompilovaného modulu.
Ve hře zůstal Swig a Boost. Ve Swigu píšete speciální wrapper, kde určíte co chcete zkompilovat do modulu. Swig pak vytvoří C++ kód modulu. Výhoda je, že máte přehled a případně můžete zdrojový kód modulu ještě upravit. Ale popravdě, ten vygenerovaný kód mi přišel dosti rozvláčný a nedokázal jsem se v něm orientovat.
Nakonec jsem zůstal u Boostu. Místo wraperu ve speciálním jazyce (jako Swig) píšete wrapper v C++ a ten rovnou kompilujete do modulu. Zdá se mi, že Boost řeší docela dobře dost věcí, automaticky převede vyjímky, poradí si s přetíženými funkcemi, metodami i konstruktory a přitom je poměrně snadný.
Zatim nebylo zmineno CFFI, ktere vzniklo v ramci PyPy. CFFI je pythonovsky modul nabizejici prostredky, jak ciste z pythonu volat C-ckovy kod. Pekny clanek s prikladem (a srovnani s Cythonem) je napriklad tu: http://me.veekun.com/blog/2013/09/13/cython-versus-cffi/
Pro zobrazení všech 9 odpovědí se prosím přihlaste:
Nebo se přihlaste jménem a heslem: