Jaki byłby najszybszy sposób na zbudowanie powiązania Pythona z biblioteką C lub C ++?
(Używam Windows, jeśli to ma znaczenie).
Powinieneś spojrzeć na Boost.Python . Oto krótkie wprowadzenie z ich strony internetowej:
Biblioteka Boost Python jest strukturą dla interfejsów Python i C ++. Pozwala szybko i bezproblemowo udostępniać funkcje i obiekty klas C ++ w Pythonie i odwrotnie, bez użycia specjalnych narzędzi - tylko kompilatora C ++. Został zaprojektowany do nieinwazyjnego pakowania interfejsów C ++, dzięki czemu nie trzeba wcale zmieniać kodu C ++, aby go zawinąć, dzięki czemu Boost.Python jest idealny do udostępniania bibliotek innych firm w Pythonie. Zastosowanie przez bibliotekę zaawansowanych technik metaprogramowania upraszcza składnię dla użytkowników, dzięki czemu zawijanie kodu przypomina wygląd deklaratywnego języka definicji interfejsu (IDL).
Moduł ctypes jest częścią standardowej biblioteki, a zatem jest bardziej stabilny i szeroko dostępny niż swig , co zawsze sprawiało mi problemy .
W przypadku ctypes musisz spełnić każdą zależność czasową kompilacji od Pythona, a twoje wiązanie będzie działać na każdym pythonie, który ma ctypy, a nie tylko na tym, z którym został skompilowany.
Załóżmy, że masz prostą przykładową klasę C ++, z którą chcesz rozmawiać w pliku o nazwie foo.cpp:
Ponieważ ctypy mogą rozmawiać tylko z funkcjami języka C, musisz podać te, które deklarują je jako zewnętrzne „C”
Następnie musisz skompilować to do biblioteki współdzielonej
I na koniec musisz napisać swoje opakowanie Pythona (np. W fooWrapper.py)
Gdy już to zrobisz, możesz to tak nazwać
źródło
extern "C" { __declspec(dllexport) Foo* Foo_new(){ return new Foo(); } __declspec(dllexport) void Foo_bar(Foo* foo){ foo->bar(); } }
Foo_delete
funkcję i wywołując ją albo z destruktora Pythona, albo zawijając obiekt w zasobie .Najszybszym sposobem na to jest użycie SWIG .
Przykład z samouczka SWIG :
Plik interfejsu:
Budowanie modułu Python na Uniksie:
Stosowanie:
Zauważ, że musisz mieć python-dev. Również w niektórych systemach pliki nagłówkowe Pythona będą w /usr/include/python2.7 w zależności od sposobu zainstalowania.
Z samouczka:
źródło
Swoją podróż rozpocząłem w powiązaniu Pythona <-> C ++ z tej strony, mając na celu połączenie typów danych wysokiego poziomu (wielowymiarowe wektory STL z listami Pythona) :-)
Po wypróbowaniu rozwiązań opartych na obu typach i boost.python (i nie będąc inżynierem oprogramowania) Znalazłem je złożone typy danych, gdy wymagany jest wysoki poziom wiązania, natomiast znalazłem haust znacznie prostsze dla takich przypadków.
W tym przykładzie użyto zatem SWIG i został on przetestowany w systemie Linux (ale SWIG jest dostępny i jest również powszechnie używany w systemie Windows).
Celem jest udostępnienie Pythonowi funkcji C ++, która przyjmuje macierz w postaci wektora 2D STL i zwraca średnią każdego wiersza (jako wektor 1D STL).
Kod w C ++ („code.cpp”) jest następujący:
Odpowiednik nagłówka („code.h”) to:
Najpierw kompilujemy kod C ++, aby utworzyć plik obiektowy:
Następnie definiujemy plik definicji interfejsu SWIG („code.i”) dla naszych funkcji C ++.
Za pomocą SWIG generujemy kod źródłowy interfejsu C ++ z pliku definicji interfejsu SWIG.
W końcu kompilujemy wygenerowany plik źródłowy interfejsu C ++ i łączymy wszystko razem, aby wygenerować bibliotekę współdzieloną, którą można bezpośrednio importować przez Python (ważne jest „_”):
Możemy teraz używać tej funkcji w skryptach Python:
źródło
Jest też
pybind11
, która jest jak lekka wersja Boost.Python i kompatybilna ze wszystkimi nowoczesnymi kompilatorami C ++:https://pybind11.readthedocs.io/en/latest/
źródło
Pytorch
Pytorch.org/tutorials/advanced/cpp_extension.html Działa również w pełni wVS Community
systemie WindowsSprawdź pyrex lub Cython . Są to języki podobne do Pythona do współpracy między C / C ++ i Python.
źródło
Dla współczesnego C ++ użyj cppyy: http://cppyy.readthedocs.io/en/latest/
Opiera się na Cling, interpretatorze C ++ dla Clang / LLVM. Wiązania są w czasie wykonywania i nie jest wymagany żaden dodatkowy język pośredni. Dzięki Clang obsługuje C ++ 17.
Zainstaluj go za pomocą pip:
W przypadku małych projektów wystarczy załadować odpowiednią bibliotekę i nagłówki, które Cię interesują. Np. Weź kod z przykładu ctypes to ten wątek, ale podzielony na sekcje nagłówka i kodu:
Skompiluj to:
i użyj go:
Duże projekty są obsługiwane przez automatyczne ładowanie przygotowanych informacji o odbiciu i fragmentów cmake do ich utworzenia, aby użytkownicy zainstalowanych pakietów mogli po prostu uruchomić:
Dzięki LLVM możliwe są zaawansowane funkcje, takie jak automatyczne tworzenie szablonów. Aby kontynuować przykład:
Uwaga: Jestem autorem cppyy.
źródło
swig
,ctypes
lubboost.python
. Zamiast pisać kod, aby Python działał z Twoim kodem c ++ ... Python wykonuje ciężką pracę, aby znaleźć c ++. Zakładając, że to faktycznie działa.Ten artykuł, w którym twierdzi się, że Python jest wszystkim, czego potrzebuje naukowiec , w zasadzie mówi: Najpierw prototypuj wszystko w Pythonie. Następnie, gdy musisz przyspieszyć część, użyj SWIG i przetłumacz tę część na C.
źródło
Nigdy go nie używałem, ale słyszałem dobre rzeczy o typach . Jeśli próbujesz używać go z C ++, pamiętaj, aby uniknąć przekłamywania nazw przez
extern "C"
. Dzięki za komentarz, Florian Bösch.źródło
Myślę, że cffi dla Pythona może być opcją.
http://cffi.readthedocs.org/en/release-0.7/
źródło
Pytanie brzmi: jak wywołać funkcję C z Pythona, jeśli dobrze zrozumiałem. Zatem najlepszym wyborem są typy Ctyp (BTW przenośne we wszystkich wariantach Pythona).
Szczegółowy przewodnik możesz znaleźć w moim blogu .
źródło
Jeden z oficjalnych dokumentów Pythona zawiera szczegółowe informacje na temat rozszerzania Pythona za pomocą C / C ++ . Nawet bez użycia SWIG jest dość prosty i działa doskonale w systemie Windows.
źródło
Cython jest zdecydowanie właściwą drogą, chyba że spodziewasz się pisać opakowania Java, w takim przypadku SWIG może być lepszym rozwiązaniem.
Polecam korzystanie z
runcython
narzędzia wiersza poleceń, dzięki czemu proces korzystania z Cython jest niezwykle łatwy. Jeśli potrzebujesz przekazać dane strukturalne do C ++, spójrz na bibliotekę protobuf Google, jest to bardzo wygodne.Oto minimalne przykłady, które stworzyłem przy użyciu obu narzędzi:
https://github.com/nicodjimenez/python2cpp
Mam nadzieję, że może to być przydatny punkt wyjścia.
źródło
Najpierw powinieneś zdecydować, jaki jest twój konkretny cel. Oficjalna dokumentacja Pythona dotycząca rozszerzania i osadzania interpretera Pythona została wspomniana powyżej, mogę dodać dobry przegląd rozszerzeń binarnych . Przypadki użycia można podzielić na 3 kategorie:
Aby dać szerszą perspektywę innym zainteresowanym, a ponieważ twoje początkowe pytanie jest nieco niejasne („do biblioteki C lub C ++”), myślę, że ta informacja może być dla ciebie interesująca. Na powyższym linku możesz przeczytać o wadach korzystania z rozszerzeń binarnych i ich alternatyw.
Oprócz innych sugerowanych odpowiedzi, jeśli chcesz moduł akceleratora, możesz wypróbować Numba . Działa „generując zoptymalizowany kod maszynowy przy użyciu infrastruktury kompilatora LLVM w czasie importu, w czasie wykonywania lub statycznie (przy użyciu dołączonego narzędzia pycc)”.
źródło
Uwielbiam cppyy, bardzo ułatwia rozszerzenie Pythona za pomocą kodu C ++, dramatycznie zwiększając wydajność w razie potrzeby.
Jest potężny i szczerze mówiąc bardzo prosty w użyciu,
tutaj jest przykład, w jaki sposób można utworzyć tablicę numpy i przekazać ją do funkcji członka klasy w C ++.
cppyy_test.py
Bufor. H
Możesz także bardzo łatwo stworzyć moduł Pythona (z CMake), dzięki czemu unikniesz ponownej kompilacji kodu C ++ przez cały czas.
źródło
pybind11 minimalny możliwy do uruchomienia przykład
pybind11 był wcześniej wspomniany na https://stackoverflow.com/a/38542539/895245, ale chciałbym podać tutaj konkretny przykład użycia i trochę dalszej dyskusji na temat implementacji.
W sumie gorąco polecam pybind11, ponieważ jest naprawdę łatwy w użyciu: wystarczy dołączyć nagłówek, a następnie pybind11 używa magii szablonów, aby sprawdzić klasę C ++, którą chcesz udostępnić Pythonowi i robi to w przejrzysty sposób.
Minusem tej magii szablonu jest to, że spowalnia kompilację, natychmiast dodając kilka sekund do dowolnego pliku korzystającego z pybind11, patrz na przykład dochodzenie przeprowadzone w tej sprawie . PyTorch zgadza się .
Oto minimalny przykład, który można uruchomić, aby poczuć, jak niesamowity jest pybind11:
class_test.cpp
class_test_main.py
Skompiluj i uruchom:
Ten przykład pokazuje, jak pybind11 pozwala bez wysiłku wystawiać
ClassTest
klasę C ++ na Pythona! Kompilacja tworzy plik o nazwie,class_test.cpython-36m-x86_64-linux-gnu.so
któryclass_test_main.py
automatycznie wybiera się jako punkt definicji plikuclass_test
natywnie zdefiniowanego modułu.Być może uświadomienie sobie, jak to jest niesamowite, zatapia się tylko wtedy, gdy próbujesz zrobić to samo ręcznie z natywnym API Pythona, zobacz na przykład ten przykład wykonania, który zawiera około 10 razy więcej kodu: https://github.com /cirosantilli/python-cheat/blob/4f676f62e87810582ad53b2fb426b74eae52aad5/py_from_c/pure.c W tym przykładzie możesz zobaczyć, jak kod C musi boleśnie i wyraźnie definiować klasę Python krok po kroku ze wszystkimi zawartymi w niej informacjami (członkowie, metody, dalej metadane ...). Zobacz też:
pybind11 twierdzi, że jest podobny do
Boost.Python
tego, o którym wspomniano na https://stackoverflow.com/a/145436/895245, ale bardziej minimalny, ponieważ jest wolny od nadęty bycia w projekcie Boost:pybind11 jest także jedyną nie-rodzimą alternatywą wyróżnioną przez aktualną dokumentację wiązania Microsoft Python C pod adresem : https://docs.microsoft.com/en-us/visualstudio/python/working-with-c-cpp-python-in- visual-studio? view = vs-2019 ( archiwum ).
Testowane na Ubuntu 18.04, pybind11 2.0.1, Python 3.6.8, GCC 7.4.0.
źródło