Po wielu szturchańcach, próbach i błędach, krzyczeniu i wydzieraniu włosów, w końcu udało mi się to zrobić. Najpierw jednak musiałem ponownie napisać moje C++ do C, co dla mnie naprawdę wymagało konwersji wszystkich zmiennych std::string
na char*
i śledzenia niektórych długości.
Kiedy skończyłem, miałem pliki .h i .c. Chciałem utworzyć jedną funkcję z kodu C dostępnego w Pythonie. Okazuje się, że Cython może skompilować twoje pliki C do rozszerzenia dla ciebie i połączyć wszystkie biblioteki za jednym razem, więc zaczynając od mojej instalacji.py, skończyło się patrząc tak:
from distutils.core import setup
from distutils.extension import Extension
from Cython.Distutils import build_ext
ext_modules=[
Extension("myext",
["myext.pyx", "../stuff.c"],
libraries=["ssl", "crypto"]
)
]
setup(
name = "myext",
cmdclass = {"build_ext": build_ext},
ext_modules = ext_modules
)
Jak widać, drugi argument do przedłużenia po prostu listę wszystkich plików, które muszą być kompilowane, Cython odrabia jak skompilować je w zależności od ich rozszerzenia pliku o ile mogę powiedzieć. Tablica bibliotek informuje kompilator Cythona, co musi być połączone (w tym przypadku owijałem niektóre elementy kryptograficzne, których nie mogłem udawać bezpośrednio przez istniejące biblioteki Pythona).
Aby rzeczywiście udostępnić moją funkcję C w pliku .pyx, należy napisać małe opakowanie w pliku .pxd. Moja myext.pxd wyglądał jak poniżej:
cdef extern from "../stuff.h":
char* myfunc(char* arg1, char* arg2, char* arg3)
W .pyx następnie użyć deklarację cimport importować tę funkcję, która jest wtedy gotowy do użycia, jakby to była jakakolwiek inna funkcja Python:
cimport myext
def my_python_func(arg1, arg2, arg3):
result = myext.myfunc(arg1, arg2, arg3)
return result
Podczas kompilacji (na Macie przynajmniej) otrzymasz plik .so, który możesz zaimportować do Pythona i uruchomić funkcje z .pyx. Może być lepszy, bardziej poprawny sposób, aby wszystko działało, ale pochodzi z doświadczenia i to było pierwsze spotkanie, które udało mi się wypracować. Byłbym bardzo zainteresowany wskazówkami, w których mógłbym pójść źle.
Aktualizacja:
Po dalszego stosowania Cython, uważam, że to było bardzo proste, aby zintegrować go z C++ też, gdy wiesz, co robisz. Udostępnienie dostępnego w C++ string
jest tak proste jak from libcpp.string cimport string
w twoim pyx/pyd. Deklarując klasę C++ jest równie łatwe, jak:
cdef extern from "MyCPPClass.h":
cdef cppclass MyCPPClass:
int foo;
string bar;
Pewnie trzeba zasadzie redeclare się .h definicję klasy w formacie pythonic, ale to niewielka cena za uzyskanie dostępu do już napisanych funkcji C++ .
Jeśli odpowiedź na Twoje pytanie została udzielona, zaznacz to pytanie jako odpowiedź. W przeciwnym razie proszę podać pytanie jeszcze raz. –
@NiklasR Twoja odpowiedź obejmowała niektóre z moich obszarów zamieszania, ale nie doprowadziła mnie do końca. Podjąłem głosowanie, ale zamierzałem napisać pełną odpowiedź na inne kawałki, które wymyśliłem, gdy mam trochę czasu do stracenia. – Endophage