
Έχω αρχίσει να σκέφτονται πάνω από τη σύνταξη ενός κορυφή τοποθέτηση βιβλιοθήκη για μια στιγμή. Ξέρω Python αρκετά καλά και το σχέδιο για την εφαρμογή πάντα σε Python για να αρχίσει με, αλλά προβλέπουν ότι μπορεί να χρειαστεί να ξανά εφαρμόσει κάποιες βασικές ρουτίνες σε ένα καταρτίζονται γλώσσα τελικά.


IIRC, ένα από τα πρωτότυπα αρμοδιοτήτων Python ήταν η γλώσσα πρωτοτύπων, ωστόσο Python είναι αρκετά φιλελεύθερη επιτρέποντας λειτουργίες, functors, τα αντικείμενα που πρέπει να περάσει σε λειτουργίες και μεθόδους, ενώ υποψιάζομαι το ίδιο δεν ισχύει και να πω C ή Fortran.


Τι πρέπει να ξέρετε για το σχεδιασμό λειτουργίες / τάξεις που οραματίζομαι θα πρέπει να διασυνδέονται στη καταρτίζονται γλώσσα; Και πόσα από αυτά τα πιθανά προβλήματα που αντιμετωπίζονται από τις βιβλιοθήκες, όπως cTypes, bgen, [SWIG](http://www.swig.org/) , [Boost.Python](http://www.boost.org/doc/libs/1_35_0/libs/python/doc/index.html) , [Cython](http://cython.org/) ή [Python SIP](http://www.riverbankcomputing.co.uk/software/sip/intro) ;


Για αυτή τη συγκεκριμένη περίπτωση χρήσης, (α εξάρτημα βιβλιοθήκη) φαντάζομαι επιτρέποντας στους χρήστες να ορίσουν μαθηματικές συναρτήσεις (Guassian, Lorentzian κλπ) ως συναρτήσεις Python οποίο μπορεί στη συνέχεια να περάσει ένα ερμηνεύεται από τη βιβλιοθήκη τοποθέτηση μεταγλωττισμένο κώδικα. Περνώντας και την επιστροφή συστοιχίες είναι επίσης απαραίτητη.

 
Προτυποποίηση με κωδικό Python πριν από τη σύνταξη
==================================================



Τέλος, ένα θέμα που πραγματικά μπορώ να βάλω μια τιμή απάντηση :). 


Έχω διερευνηθεί f2py, boost.python, γουλιά, cython και πυρέξ για την εργασία μου (PhD στις τεχνικές οπτικής μέτρησης). Θα χρησιμοποιηθεί γουλιά εκτενώς, boost.python μερικές και πυρέξ και cython πολλά. Θα χρησιμοποιηθεί επίσης ctypes. Αυτή είναι η ανάλυση μου:


**Αποποίηση** : Αυτή είναι η προσωπική μου εμπειρία. Δεν εμπλέκομαι με οποιοδήποτε από αυτά τα έργα.


**swig:** 
δεν παίζει καλά με ++ γ. Θα πρέπει, αλλά το όνομα που κατασπαράζουν τα προβλήματα στο στάδιο της σύνδεσης ήταν ένας μεγάλος πονοκέφαλος για μένα σε Linux και Mac OS X. Εάν έχετε κωδικό C και θέλουν να διασυνδεθεί με python, είναι μια καλή λύση. Έχω τυλιγμένο τις GTS για τις ανάγκες μου και έπρεπε να γράψω ουσιαστικά ένα C κοινή βιβλιοθήκη που θα μπορούσα να συνδεθείτε. Εγώ δεν θα το συνιστούσα.


**Ctypes:** 
Έγραψα ένα περιτύλιγμα libdc1394 (IEEE βιβλιοθήκη κάμερα) με τη χρήση ctypes και ήταν μια πολύ straigtforward εμπειρία. Μπορείτε να βρείτε τον κωδικό στο <https://launchpad.net/pydc1394> . Είναι πολλή δουλειά για να μετατρέψει τις κεφαλίδες σε κώδικα python, αλλά στη συνέχεια όλα λειτουργούν αξιόπιστα. Αυτός είναι ένας καλός τρόπος, αν θέλετε να διασυνδέσει μια εξωτερική βιβλιοθήκη. Ctypes είναι επίσης στην stdlib του πύθωνα, έτσι ώστε ο καθένας μπορεί να χρησιμοποιήσει τον κωδικό σας αμέσως. Αυτό είναι επίσης ένας καλός τρόπος για να παίξει γύρω με ένα νέο lib σε python γρήγορα. Μπορώ να το συστήσω σε διασύνδεση με εξωτερικές libs.


**Boost.Python** : Πολύ ευχάριστη. Αν έχετε ήδη κωδικό C ++ της δικής σας που θέλετε να χρησιμοποιήσετε σε python, πάμε για αυτό. Είναι πολύ εύκολο να μεταφράσει τις δομές γ τάξη ++ σε δομές python τάξη με αυτόν τον τρόπο. Θα το συνιστούσα αν έχετε C ++ κώδικα που χρειάζεστε σε python.


**Πυρέξ / Cython:** Χρήση Cython, δεν πυρέξ. Περίοδος. Cython είναι πιο προηγμένη και πιο ευχάριστη στη χρήση. Σήμερα, κάνω τα πάντα με cython που συνήθιζα να κάνω με SWIG ή Ctypes. Επίσης, είναι ο καλύτερος τρόπος αν έχετε κωδικό Python που τρέχει πολύ αργά. Η διαδικασία είναι απολύτως φανταστική: να μετατρέψετε μονάδες python σας σε ενότητες cython, την κατασκευή τους και να διατηρήσουν προφίλ και τη βελτιστοποίηση, όπως ήταν ακόμα python (καμία αλλαγή των εργαλείων που απαιτούνται). Στη συνέχεια μπορείτε να εφαρμόσετε όσο (ή λίγο) τον κωδικό C αναμιγνύεται με κωδικό python σας. Αυτό είναι κατά πολύ πιο γρήγορα στη συνέχεια να ξαναγράψει ολόκληρα τμήματα της εφαρμογής σας σε C? θα ξαναγράψει μόνο το εσωτερικό βρόχο.


**Χρονισμός** : ctypes έχει το υψηλότερο εναέρια κλήση (~ 700ns), ακολουθούμενη από boost.python (322ns), τότε άμεσα από swig (290ns). Cython έχει το χαμηλότερο εναέρια κλήση (124ns) και την καλύτερη ανατροφοδότηση όπου ξοδεύει το χρόνο στην (υποστήριξη cProfile!). Οι αριθμοί είναι από το κουτί μου ζητά ένα ασήμαντο συνάρτηση που επιστρέφει έναν ακέραιο από ένα διαδραστικό κέλυφος? εναέρια μονάδα εισαγωγής ως εκ τούτου δεν χρονικά, λειτουργεί μόνο εναέρια κλήση. Συνεπώς, είναι πιο εύκολο και πιο παραγωγικό να πάρετε τον κωδικό python γρήγορα από προφίλ και τη χρήση cython.


**Περίληψη** : Για το πρόβλημά σας, χρησιμοποιήστε Cython?). Ελπίζω ότι αυτό υποβαθμισμένο θα είναι χρήσιμο για μερικούς ανθρώπους. Θα απαντήσω ευχαρίστως κάθε υπόλοιπο ερώτηση.




---


**Επεξεργασία** : ξεχάσω να αναφέρω: για αριθμητικούς λόγους (δηλαδή, σύνδεση με NumPy) χρησιμοποιούν Cython? έχουν υποστήριξη για αυτό (γιατί ουσιαστικά την ανάπτυξη cython για το σκοπό αυτό). Έτσι, αυτό θα πρέπει να είναι μια άλλη +1 για την απόφασή σας.

 

Στην εμπειρία μου, υπάρχουν δύο εύκολοι τρόποι για να καλέσετε σε κώδικα C από τον κώδικα Python. Υπάρχουν και άλλες προσεγγίσεις, οι οποίες είναι περισσότερο ενοχλητικό ή / και φλύαρη.


Ο πρώτος και ευκολότερος είναι να δημιουργηθεί ένα μάτσο κώδικα C ως ξεχωριστή κοινόχρηστη βιβλιοθήκη και στη συνέχεια να καλέσετε αξιωματούχων στην εν λόγω βιβλιοθήκη χρησιμοποιώντας ctypes. Δυστυχώς, περνώντας οτιδήποτε άλλο εκτός από βασικοί τύποι δεδομένων είναι μη τετριμμένη.


Ο δεύτερος πιο εύκολος τρόπος είναι να γράψει μια ενότητα Python σε C και στη συνέχεια να καλέσετε λειτουργίες σε αυτή την ενότητα. Μπορείτε να περάσετε ό, τι θέλετε σε αυτές τις λειτουργίες C χωρίς να χρειάζεται να πηδούν μέσα από τις στεφάνες. Και είναι εύκολο να καλέσετε λειτουργίες ή τις μεθόδους Python από αυτές τις λειτουργίες C, όπως περιγράφεται εδώ: <https://docs.python.org/extending/extending.html#calling-python-functions-from-c>


Δεν έχω αρκετή εμπειρία με SWIG να προσφέρει έξυπνο σχόλιο. Και ενώ είναι δυνατόν να κάνουμε τα πράγματα όπως πέρασμα προσαρμοσμένα αντικείμενα Python σε λειτουργίες C μέσω ctypes, ή να καθορίσει νέες κατηγορίες Python σε C, αυτά τα πράγματα είναι ενοχλητικό και φλύαρη και ήθελα να συστήσω τη λήψη ενός από τα δύο προσεγγίσεις που περιγράφονται παραπάνω.

 

Ο καλύτερος τρόπος για να προγραμματίσουν για μια ενδεχόμενη μετάβαση σε μεταγλωττισμένο κώδικα είναι να γράψει τα ευαίσθητα απόδοση τμημάτων ως μονάδα απλών λειτουργιών σε ένα [λειτουργικό στιλ](http://en.wikipedia.org/wiki/Functional_programming) (απάτριδες και χωρίς παρενέργειες), οι οποίες δέχονται και να επιστρέψει βασικοί τύποι δεδομένων.


Αυτό θα παρέχει μια χαρτογράφηση ένας-προς-έναν από το Python πρωτότυπο κωδικό σας για την τελική μεταγλωττισμένο κώδικα, και θα σας αφήσει να χρησιμοποιήσετε [ctypes](https://docs.python.org/library/ctypes.html) εύκολα και να αποφύγει ένα σωρό πονοκεφάλους.


Για τοποθέτηση αιχμής, θα είναι σχεδόν βέβαιο ότι πρέπει να χρησιμοποιήσετε πίνακες, που θα περιπλέξει τα πράγματα λίγο, αλλά εξακολουθεί να είναι πολύ εφικτό με ctypes.


Αν θέλετε πραγματικά να χρησιμοποιήσετε πιο πολύπλοκες δομές δεδομένων, ή να τροποποιήσει τους περάσει επιχειρήματα, [SWIG](http://www.swig.org/) ή [τυποποιημένη διεπαφή C-επέκταση της Python](https://docs.python.org/extending/) θα σας αφήσει να κάνετε ό, τι θέλετε, αλλά με κάποιο ποσό ταλαιπωρία.


Για ό, τι κάνετε, μπορείτε επίσης να θελήσετε να ελέγξετε έξω [NumPy](http://numpy.scipy.org/) , το οποίο θα μπορούσε να κάνει ορισμένες από τις εργασίες που θα θέλατε να ωθήσει προς C, καθώς και να προσφέρει [κάποια επιπλέον βοήθεια στην κίνηση δεδομένων εμπρός και πίσω μεταξύ Python και C](http://projects.scipy.org/scipy/numpy/wiki/NumPyCAPI) .

 

Δεν έχω χρησιμοποιήσει SWIG ή SIP, αλλά θεωρώ ότι το γράψιμο περιτυλίγματα Python με [boost.python](http://www.boost.org/doc/libs/1_35_0/libs/python/doc/index.html) να είναι πολύ ισχυρή και σχετικά εύκολο στη χρήση.


Δεν είμαι σαφής για το τι απαιτήσεις σας είναι για τη διέλευση των τύπων μεταξύ C / C ++ και Python, αλλά μπορείτε να το κάνετε εύκολα, είτε εκθέτοντας ένα C ++ τύπου σε python, ή μέσω μιας γενικής [ώθηση :: python :: αντικείμενο](http://www.boost.org/doc/libs/1_35_0/libs/python/doc/v2/object.html) επιχείρημα για να σας C ++ API. Μπορείτε επίσης να εγγραφείτε μετατροπείς για να μετατρέψει αυτόματα τους τύπους python σε C ++ τύπους και αντίστροφα.


Αν σκοπεύετε χρήση boost.python, το [φροντιστήριο](http://www.boost.org/doc/libs/1_35_0/libs/python/doc/tutorial/doc/html/index.html) είναι ένα καλό μέρος για να ξεκινήσετε.


Έχω υλοποιηθεί κάτι κάπως παρόμοιο με ό, τι χρειάζεστε. Έχω μια λειτουργία C ++ που δέχεται μια λειτουργία python και μια εικόνα ως επιχειρήματα, και εφαρμόζει τη λειτουργία python σε κάθε pixel της εικόνας.



```
Image* unary(boost::python::object op, Image& im)
{
    Image* out = new Image(im.width(), im.height(), im.channels());
    for(unsigned int i=0; i<im.size(); i++)
    {
        (*out)[i] == extract<float>(op(im[i]));
    }
    return out;
}

```

Σε αυτή την περίπτωση, η εικόνα είναι ένα C ++ αντικείμενο εκτεθεί σε python (μια εικόνα με εικονοστοιχεία float), και op είναι μια καθορισμένη λειτουργία python (ή πραγματικά οποιοδήποτε αντικείμενο πύθωνα με ένα χαρακτηριστικό \_\_call\_\_). Στη συνέχεια, μπορείτε να χρησιμοποιήσετε αυτή τη λειτουργία ως εξής (υποθέτοντας μοναδιαίο βρίσκεται στην ονομάζεται εικόνα που περιέχει, επίσης, Εικόνα και μια λειτουργία φορτίο):



```
import image
im = image.load('somefile.tiff')
double_im = image.unary(lambda x: 2.0*x, im)

```

Όσο για τη χρήση συστοιχιών με ώθηση, εγώ προσωπικά δεν το έχετε κάνει, αλλά ξέρω τη λειτουργία για να εκθέσει πίνακες σε Python χρησιμοποιώντας ώθηση είναι διαθέσιμη - [αυτό](http://www.boost.org/doc/libs/1_35_0/libs/python/doc/v2/faq.html#question2) θα μπορούσε να είναι χρήσιμη.

 

[f2py](http://cens.ioc.ee/projects/f2py2e/usersguide/index.html#the-quick-and-smart-way) (μέρος της `numpy`) είναι μια απλούστερη εναλλακτική λύση για Γουλιά και boost.python για την περιτύλιξη C / Fortran κωδικό αριθμό-τραγάνισμα.

 


> 
> Python είναι αρκετά φιλελεύθερη επιτρέποντας λειτουργίες, functors, τα αντικείμενα που πρέπει να περάσει σε λειτουργίες και μεθόδους, ενώ υποψιάζομαι το ίδιο δεν ισχύει και να πω C ή Fortran.
> 
> 
> 


Στην C δεν μπορείτε να περάσετε μια λειτουργία ως επιχείρημα σε μια λειτουργία, αλλά μπορείτε να περάσετε ένα δείκτη λειτουργία η οποία είναι εξίσου καλή λειτουργία.


Δεν ξέρω πόσο που θα σας βοηθήσει όταν προσπαθείτε να ενσωματώσει C και τον κωδικό Python, αλλά θα ήθελα απλώς να ξεκαθαρίσω μια παρανόηση.

 

Εκτός από τα παραπάνω εργαλεία, μπορώ να συστήσω χρησιμοποιώντας [Pyrex](http://www.cosc.canterbury.ac.nz/greg.ewing/python/Pyrex/ "πυρέξ") 
(για τη δημιουργία μονάδες επέκτασης Python) ή [Psyco](http://psyco.sourceforge.net/ "Psyco") (όπως μεταγλωττιστή ΚΟΕ για Python).

 