पायथन से C / C ++ को कॉल करना?


521

C या C ++ लाइब्रेरी के लिए पायथन बाइंडिंग बनाने का सबसे तेज़ तरीका क्या होगा?

(यदि मैं Windows का उपयोग कर रहा हूँ तो यह मायने रखता है।)

जवाबों:


170

आपको Boost.Python पर एक नजर डालनी चाहिए । यहाँ उनकी वेबसाइट से लिया गया संक्षिप्त परिचय दिया गया है:

बूस्ट पायथन लाइब्रेरी पाइथन और C ++ के बीच तालमेल बिठाने की एक रूपरेखा है। यह आपको बिना किसी विशेष टूल का उपयोग किए, केवल आपके C ++ कंपाइलर का उपयोग करके C ++ वर्ग फ़ंक्शंस और ऑब्जेक्ट्स को तेज़ी से और मूल रूप से उजागर करने देता है। इसे C ++ इंटरफेस को गैर-आंतरिक रूप से लपेटने के लिए डिज़ाइन किया गया है, ताकि आपको इसे लपेटने के लिए C ++ कोड को बिल्कुल भी बदलना न पड़े, जिससे Boost.Python 3-पार्टी लाइब्रेरीज़ को Python में एक्सपोज़ करने के लिए आदर्श हो। लाइब्रेरी के उन्नत मेटाप्रोग्रामिंग तकनीकों का उपयोग उपयोगकर्ताओं के लिए इसके सिंटैक्स को सरल करता है, ताकि रैपिंग कोड एक तरह की घोषणात्मक इंटरफ़ेस परिभाषा भाषा (आईडीएल) का रूप ले ले।


Boost.Python Boost में एक अधिक उपयोगकर्ता के अनुकूल पुस्तकालय है, एक साधारण फ़ंक्शन कॉल API के लिए यह काफी सीधा है और यह बॉयलरप्लेट प्रदान करता है जिसे आपको स्वयं लिखना होगा। यदि आप ऑब्जेक्ट-ओरिएंटेड एपीआई को उजागर करना चाहते हैं तो यह थोड़ा अधिक जटिल है।
jwfearn

15
Boost.Python सबसे बुरी चीज है जिसकी कल्पना की जा सकती है। हर नई मशीन के लिए और हर अपग्रेड के साथ यह लिंकिंग समस्याओं के साथ जाता है।
मिलर

14
इस उत्तर की गुणवत्ता के बारे में कुछ चिंतन के लिए लगभग 11 साल बाद का समय?
जे इवांस

4
क्या यह अभी भी इंटरफ़ेस पायथन और c ++ के लिए सबसे अच्छा तरीका है?
तुषार

8
शायद आप pybind11 को आज़मा सकते हैं जो कि बूस्ट की तुलना में हल्का है।
jdhao

658

ctypes मॉड्यूल मानक पुस्तकालय का हिस्सा है, और इसलिए यह स्वाइप की तुलना में अधिक स्थिर और व्यापक रूप से उपलब्ध है , जो हमेशा मुझे समस्याएं देने के लिए प्रेरित करता था ।

Ctypes के साथ, आपको अजगर पर किसी भी संकलन समय निर्भरता को संतुष्ट करने की आवश्यकता है, और आपका बंधन किसी भी अजगर पर काम करेगा जिसमें ctypes है, न कि केवल उसी के खिलाफ संकलित किया गया था।

मान लें कि आपके पास एक सरल C ++ उदाहरण वर्ग है जिसे आप foo.cpp नामक फ़ाइल में बात करना चाहते हैं:

#include <iostream>

class Foo{
    public:
        void bar(){
            std::cout << "Hello" << std::endl;
        }
};

चूंकि ctypes केवल C फ़ंक्शन से बात कर सकते हैं, इसलिए आपको उन्हें "C" बाहरी घोषित करने की आवश्यकता होगी।

extern "C" {
    Foo* Foo_new(){ return new Foo(); }
    void Foo_bar(Foo* foo){ foo->bar(); }
}

आगे आपको इसे साझा लाइब्रेरी में संकलित करना होगा

g++ -c -fPIC foo.cpp -o foo.o
g++ -shared -Wl,-soname,libfoo.so -o libfoo.so  foo.o

और अंत में आपको अपना अजगर आवरण लिखना होगा (उदाहरण के लिए fooWrapper.py)

from ctypes import cdll
lib = cdll.LoadLibrary('./libfoo.so')

class Foo(object):
    def __init__(self):
        self.obj = lib.Foo_new()

    def bar(self):
        lib.Foo_bar(self.obj)

एक बार जब आपके पास ऐसा हो तो आप इसे कॉल कर सकते हैं

f = Foo()
f.bar() #and you will see "Hello" on the screen

14
यह बहुत ज्यादा है जो एक ही फ़ंक्शन कॉल में आपके लिए बूस्टहोमथॉन करता है।
मार्टिन बेकेट

202
ctypes अजगर मानक पुस्तकालय में है, swig और बढ़ावा नहीं है। स्वाइप और बूस्ट एक्सटेंशन मॉड्यूल पर भरोसा करते हैं और इसलिए अजगर छोटे संस्करणों से बंधे होते हैं जो कि अप्रत्यक्ष रूप से साझा किए गए ऑब्जेक्ट नहीं होते हैं। स्विग या बूस्ट रैपर्स का निर्माण एक दर्द हो सकता है, ctypes कोई निर्माण आवश्यकताओं को नहीं बनाता है।
फ्लोरियन बॉश

25
बूस्ट वूडू टेम्पलेट मैजिक और एक पूरी तरह से कस्टम बिल्ड सिस्टम पर निर्भर करता है, ctypes सादगी पर निर्भर करता है। ctypes गतिशील है, बढ़ावा स्थिर है। ctypes पुस्तकालयों के विभिन्न संस्करणों को संभाल सकता है। बूस्ट नहीं हो सकता।
फ्लोरियन बॉश

32
विंडोज पर मुझे पायथन के लिए अपने फ़ंक्शन हस्ताक्षरों में __declspec (dllexport) निर्दिष्ट करना होगा, ताकि वे उन्हें देख सकें। उपरोक्त उदाहरण से यह मेल खाती है: extern "C" { __declspec(dllexport) Foo* Foo_new(){ return new Foo(); } __declspec(dllexport) void Foo_bar(Foo* foo){ foo->bar(); } }
एलन मैकडोनाल्ड

13
किसी Foo_deleteफ़ंक्शन को प्रदान करने और उसे अजगर डिस्ट्रॉक्टर से कॉल करके या संसाधन में ऑब्जेक्ट को लपेटकर बाद में पॉइंटर को हटाना न भूलें ।
एडवर्सस

58

ऐसा करने का सबसे तेज़ तरीका SWIG का उपयोग कर रहा है ।

SWIG ट्यूटोरियल से उदाहरण :

/* File : example.c */
int fact(int n) {
    if (n <= 1) return 1;
    else return n*fact(n-1);
}

इंटरफ़ेस फ़ाइल:

/* example.i */
%module example
%{
/* Put header files here or function declarations like below */
extern int fact(int n);
%}

extern int fact(int n);

यूनिक्स पर एक पायथन मॉड्यूल का निर्माण:

swig -python example.i
gcc -fPIC -c example.c example_wrap.c -I/usr/local/include/python2.7
gcc -shared example.o example_wrap.o -o _example.so

उपयोग:

>>> import example
>>> example.fact(5)
120

ध्यान दें कि आपके पास अजगर-देव होना चाहिए। इसके अलावा कुछ सिस्टमों में अजगर हेडर फाइलें /usr/include/python2.7 में आपके द्वारा इंस्टॉल किए गए तरीके के आधार पर होंगी।

ट्यूटोरियल से:

SWIG लगभग हर भाषा सुविधा के समर्थन के साथ एक काफी पूर्ण C ++ कंपाइलर है। इसमें प्रीप्रोसेसिंग, पॉइंटर्स, क्लासेस, इनहेरिटेंस और यहां तक ​​कि C ++ टेम्प्लेट शामिल हैं। SWIG का उपयोग लक्ष्य भाषा में प्रॉक्सी कक्षाओं में संरचनाओं और कक्षाओं को पैकेज करने के लिए भी किया जा सकता है - बहुत स्वाभाविक तरीके से अंतर्निहित कार्यक्षमता को उजागर करना।


49

मैंने इस पृष्ठ से पायथन <-> C ++ में अपनी यात्रा शुरू की, जिसका उद्देश्य उच्च स्तर के डेटा प्रकारों को जोड़ना है (पायथन सूचियों के साथ बहुआयामी एसटीएल वैक्टर) :-)

दोनों ctypes और बूस्टहोमथॉन (और एक सॉफ्टवेयर इंजीनियर नहीं होने) के आधार पर समाधानों की कोशिश करने के बाद, मैंने उन्हें उच्च स्तरीय डेटाटाइप्स बाइंडिंग की आवश्यकता होने पर जटिल पाया है, जबकि मैंने SWIG पाया है ऐसे मामलों के लिए अधिक सरल ।

यह उदाहरण इसलिए SWIG का उपयोग करता है, और इसे लिनक्स में परीक्षण किया गया है (लेकिन SWIG उपलब्ध है और व्यापक रूप से विंडोज में भी उपयोग किया जाता है)।

इसका उद्देश्य पायथन को सी ++ फ़ंक्शन उपलब्ध कराना है जो 2 डी एसटीएल वेक्टर के रूप में एक मैट्रिक्स लेता है और प्रत्येक पंक्ति के औसत (1 डी एसटीएल वेक्टर के रूप में) देता है।

C ++ में कोड ("code.cpp") निम्नानुसार है:

#include <vector>
#include "code.h"

using namespace std;

vector<double> average (vector< vector<double> > i_matrix) {

  // Compute average of each row..
  vector <double> averages;
  for (int r = 0; r < i_matrix.size(); r++){
    double rsum = 0.0;
    double ncols= i_matrix[r].size();
    for (int c = 0; c< i_matrix[r].size(); c++){
      rsum += i_matrix[r][c];
    }
    averages.push_back(rsum/ncols);
  }
  return averages;
}

समतुल्य शीर्ष लेखिका ("code.h") है:

#ifndef _code
#define _code

#include <vector>

std::vector<double> average (std::vector< std::vector<double> > i_matrix);

#endif

ऑब्जेक्ट फ़ाइल बनाने के लिए हम पहले C ++ कोड संकलित करते हैं:

g++ -c -fPIC code.cpp

फिर हम अपने C ++ फ़ंक्शंस के लिए एक SWIG इंटरफ़ेस परिभाषा फ़ाइल ("code.i") को परिभाषित करते हैं।

%module code
%{
#include "code.h"
%}
%include "std_vector.i"
namespace std {

  /* On a side note, the names VecDouble and VecVecdouble can be changed, but the order of first the inner vector matters! */
  %template(VecDouble) vector<double>;
  %template(VecVecdouble) vector< vector<double> >;
}

%include "code.h"

SWIG का उपयोग करके, हम SWIG इंटरफ़ेस परिभाषा फ़ाइल से C ++ इंटरफ़ेस स्रोत कोड उत्पन्न करते हैं।

swig -c++ -python code.i

हम अंततः उत्पन्न C ++ इंटरफ़ेस स्रोत फ़ाइल संकलित करते हैं और एक साझा लाइब्रेरी को उत्पन्न करने के लिए सब कुछ एक साथ जोड़ते हैं जो सीधे पायथन ("_" मामलों) द्वारा आयात करने योग्य है:

g++ -c -fPIC code_wrap.cxx  -I/usr/include/python2.7 -I/usr/lib/python2.7
g++ -shared -Wl,-soname,_code.so -o _code.so code.o code_wrap.o

अब हम पायथन लिपियों में फ़ंक्शन का उपयोग कर सकते हैं:

#!/usr/bin/env python

import code
a= [[3,5,7],[8,10,12]]
print a
b = code.average(a)
print "Assignment done"
print a
print b

एक वास्तविक मामला कार्यान्वयन जहां C ++ कोड में stl वैक्टर को नॉन कास्ट
Antonello

33

वहाँ भी है pybind11, जो Boost.Python के हल्के संस्करण की तरह है और सभी आधुनिक C ++ कंपाइलर के साथ संगत है:

https://pybind11.readthedocs.io/en/latest/


1
आज !! 2020 यह शीर्ष उत्तर होना चाहिए! यह एक टेम्पलेट हैडर केवल पुस्तकालय है। कई विशाल प्रासंगिक परियोजनाएं इसकी अनुशंसा करती हैं, जैसे Pytorch pytorch.org/tutorials/advanced/cpp_extension.html यह भी पूरी तरह से VS Communityविंडोज पर काम करता है
eusoubrasileiro

30

पाइरेक्स या साइथन की जाँच करें । वे C / C ++ और Python के बीच अंतर करने के लिए पायथन जैसी भाषाएं हैं।


1
साइथन के लिए +1! मैंने cffi की कोशिश नहीं की है, इसलिए मैं यह नहीं कह सकता कि कौन बेहतर है, लेकिन मुझे साइथन के साथ बहुत अच्छे अनुभव थे - आप अभी भी पायथन कोड लिख रहे हैं, लेकिन आप इसमें C का उपयोग कर सकते हैं। मेरे लिए साइथन के
Martinsos

हो सकता है कि आप उत्तर को सुधारना चाहते हों, अब लिंक-ओनली उत्तर नहीं होगा।
एडलीन

मैं लगभग एक सप्ताह से साइथॉन का उपयोग कर रहा हूं और मुझे यह बहुत पसंद है: 1) मैंने ctypes को उपयोग में देखा है और यह बहुत ही कमज़ोर है और कई दोषों से ग्रस्त है 2) यह आपको कुछ पायथन कोड लेने और इसे गति देने की अनुमति देता है अकेले चीजों को टाइप करने से 3) सी / सी ++ विधियों और वस्तुओं 4 के लिए पायथन रैपर लिखना सीधा है। यह अभी भी अच्छी तरह से समर्थित है। यह अधिक मार्गदर्शन के साथ-साथ वीवीएस और क्रॉस-संकलन को स्थापित कर सकता है, जिससे काम करने में थोड़ा समय लगता है। यहाँ बहुत अच्छा 4 घंटे का वीडियो ट्यूटोरियल है: youtube.com/watch?v=gMvkiQ-gOW8
Den-Jason

22

आधुनिक C ++ के लिए, cppyy का उपयोग करें: http://cppyy.readthedocs.io/en/latest/

यह Cling, Cl ++ / LLVM के लिए C ++ दुभाषिया पर आधारित है। बाइंडिंग रन-टाइम पर है और कोई अतिरिक्त मध्यवर्ती भाषा आवश्यक नहीं है। क्लैंग के लिए धन्यवाद, यह C ++ 17 का समर्थन करता है।

पाइप का उपयोग करके इसे स्थापित करें:

    $ pip install cppyy

छोटी परियोजनाओं के लिए, संबंधित लाइब्रेरी और उन हेडर को लोड करें, जिनमें आप रुचि रखते हैं। जैसे ctypes उदाहरण से कोड लेते हैं यह थ्रेड है, लेकिन हेडर और कोड सेक्शन में विभाजित है:

    $ cat foo.h
    class Foo {
    public:
        void bar();
    };

    $ cat foo.cpp
    #include "foo.h"
    #include <iostream>

    void Foo::bar() { std::cout << "Hello" << std::endl; }

इसे संकलित करें:

    $ g++ -c -fPIC foo.cpp -o foo.o
    $ g++ -shared -Wl,-soname,libfoo.so -o libfoo.so  foo.o

और इसका उपयोग करें:

    $ python
    >>> import cppyy
    >>> cppyy.include("foo.h")
    >>> cppyy.load_library("foo")
    >>> from cppyy.gbl import Foo
    >>> f = Foo()
    >>> f.bar()
    Hello
    >>>

बड़ी परियोजनाओं को तैयार प्रतिबिंब जानकारी के ऑटो-लोडिंग और उन्हें बनाने के लिए सीमेक टुकड़ों के साथ समर्थन किया जाता है, ताकि स्थापित पैकेजों के उपयोगकर्ता बस उपयोग कर सकें:

    $ python
    >>> import cppyy
    >>> f = cppyy.gbl.Foo()
    >>> f.bar()
    Hello
    >>>

एलएलवीएम के लिए धन्यवाद, उन्नत सुविधाएँ संभव हैं, जैसे कि स्वचालित टेम्पलेट तात्कालिकता। उदाहरण जारी रखने के लिए:

    >>> v = cppyy.gbl.std.vector[cppyy.gbl.Foo]()
    >>> v.push_back(f)
    >>> len(v)
    1
    >>> v[0].bar()
    Hello
    >>>

नोट: मैं दुखी का लेखक हूं।


3
यह वास्तव में नहीं है: साइथन पायथन के लिए सी एक्सटेंशन मॉड्यूल लिखने के लिए पायथन जैसी प्रोग्रामिंग भाषा है (साइथन कोड सी में अनुवादित हो जाता है, साथ में आवश्यक सी-एपीआई बॉयलरप्लेट)। यह कुछ मूल C ++ सहायता प्रदान करता है। दु: खद के साथ प्रोग्रामिंग में केवल पायथन और सी ++ शामिल हैं, कोई भाषा एक्सटेंशन नहीं है। यह पूरी तरह से रन-टाइम है और ऑफ़लाइन कोड उत्पन्न नहीं करता है (आलसी पीढ़ी बहुत बेहतर होती है)। यह आधुनिक C ++ (incl। स्वत: टेम्पलेट इंस्टांलेशन, मूव्स, initializer_lists, lambda's, आदि) को लक्षित करता है और PyPy को मूल रूप से समर्थित है (यानी धीमी C-API इम्यूलेशन लेयर के माध्यम से नहीं)।
विम लाव्रीसेन

2
इस PyHPC'16 पेपर में बेंचमार्क संख्याओं की एक सीमा होती है। तब से, हालांकि, सीपीथॉन की ओर से निश्चित सुधार हुए हैं।
विम लावरिसेन

मैं इस दृष्टिकोण की तरह है क्योंकि आप के साथ अतिरिक्त एकीकरण काम करने के लिए की जरूरत नहीं है swig, ctypesया boost.python। आपके बजाय अपने c ++ कोड के साथ काम करने के लिए अजगर पाने के लिए कोड लिखना होगा ... python c ++ का पता लगाने के लिए कड़ी मेहनत करता है। यह मानते हुए कि यह वास्तव में काम करता है।
ट्रेवर बॉयड स्मिथ

बहुत ही दिलचस्प है! मैं डॉक्स में देखता हूं कि पुनर्वितरण और पूर्व-पैकेजिंग को संभाला जाता है। क्या यह उन उपकरणों के साथ अच्छी तरह से काम करने के लिए जाना जाता है जो अजगर कोड को भी पैकेज करते हैं (जैसे, PyInstaller)? और क्या यह ROOT प्रोजेक्ट से संबंधित है, या इसके काम का लाभ उठा रहा है?
जिम

धन्यवाद! मैं PyInstaller से परिचित नहीं हूं, लेकिन "डिक्शनरी" जो कि आगे की घोषणाओं, पथों और हेडर को पैकेज करती है, C ++ कोड हैं जो साझा किए गए कामों के लिए संकलित हैं। चूंकि C ++ कोड को बांधने के लिए cppyy का उपयोग किया जाता है, इसलिए मुझे लगता है कि कुछ और C ++ कोड को संभालना ठीक होना चाहिए। और वह कोड पायथन सी-एपीआई (केवल लीबक्रेपी मॉड्यूल) पर निर्भर नहीं है, जो चीजों को सरल करता है। cppyy खुद को conda-forge या pypi (पाइप) से स्थापित किया जा सकता है, इसलिए उनमें से कोई भी वातावरण, निश्चित रूप से काम करता है। हां, पियरे से कांटा शुरू हो गया, लेकिन यह तब से बहुत सुधर गया है, रोओटी टीम दुखी होकर पायरोट को पछाड़ रही है।
विवि लव्रीसेन

20

यह पेपर, सभी वैज्ञानिक जरूरतों के लिए पायथन का दावा करता है , मूल रूप से कहता है: पायथन में सब कुछ पहले प्रोटोटाइप। फिर जब आपको किसी भाग को गति देने की आवश्यकता हो, तो SWIG का उपयोग करें और इस भाग को C में अनुवाद करें।


15

मैंने इसका कभी उपयोग नहीं किया है लेकिन मैंने ctypes के बारे में अच्छी बातें सुनी हैं । यदि आप इसे C ++ के साथ उपयोग करने का प्रयास कर रहे हैं, तो नाम के माध्यम से नामकरण से बचना सुनिश्चित करें extern "C"टिप्पणी के लिए धन्यवाद, फ्लोरियन बोश।


13

मुझे लगता है कि अजगर के लिए cffi एक विकल्प हो सकता है।

लक्ष्य पायथन से सी कोड को कॉल करना है। आपको तीसरी भाषा सीखे बिना ऐसा करने में सक्षम होना चाहिए: हर विकल्प के लिए आपको उनकी खुद की भाषा (साइथन, स्विग) या एपीआई (ctypes) सीखने की आवश्यकता होती है। इसलिए हमने यह मानने की कोशिश की कि आप पायथन और सी को जानते हैं और एपीआई के अतिरिक्त बिट्स को कम से कम करते हैं जो आपको सीखने की जरूरत है।

http://cffi.readthedocs.org/en/release-0.7/


2
मुझे लगता है कि यह केवल c (c ++ नहीं) कह सकता है, फिर भी +1 (मुझे वास्तव में cffi पसंद है)।
एंडी हेडन

8

सवाल यह है कि पायथन से सी फ़ंक्शन को कैसे कॉल किया जाए, अगर मैं सही ढंग से समझ गया। फिर सबसे अच्छा दांव सीटीप्स (पाइथन के सभी वेरिएंट्स में बीटीडब्ल्यू पोर्टेबल) हैं।

>>> from ctypes import *
>>> libc = cdll.msvcrt
>>> print libc.time(None)
1438069008
>>> printf = libc.printf
>>> printf("Hello, %s\n", "World!")
Hello, World!
14
>>> printf("%d bottles of beer\n", 42)
42 bottles of beer
19

एक विस्तृत गाइड के लिए आप मेरे ब्लॉग लेख का संदर्भ लेना चाह सकते हैं ।


यह ध्यान देने योग्य हो सकता है कि ctypes पोर्टेबल होने के दौरान, आपके कोड को Windows- विशिष्ट C लाइब्रेरी की आवश्यकता होती है।
पालिक

7

आधिकारिक पायथन दस्तावेजों में से एक में C / C ++ का उपयोग करके अजगर को विस्तारित करने के बारे में विवरण हैSWIG के उपयोग के बिना भी , यह काफी सीधा है और विंडोज पर पूरी तरह से काम करता है।


6

साइथन निश्चित रूप से जाने का रास्ता है, जब तक आप जावा रैपर लिखने का अनुमान नहीं लगाते हैं, जिस स्थिति में SWIG बेहतर हो सकता है।

मैं runcythonकमांड लाइन उपयोगिता का उपयोग करने की सलाह देता हूं , यह साइथन का उपयोग करने की प्रक्रिया को बहुत आसान बनाता है। यदि आपको संरचित डेटा को C ++ में पास करने की आवश्यकता है, तो Google के प्रोटोबॉफ़ पुस्तकालय पर एक नज़र डालें, यह बहुत सुविधाजनक है।

यहाँ एक न्यूनतम उदाहरण है जो मैंने बनाया है जो दोनों उपकरणों का उपयोग करता है:

https://github.com/nicodjimenez/python2cpp

आशा है कि यह एक उपयोगी प्रारंभिक बिंदु हो सकता है।


5

पहले आपको यह तय करना चाहिए कि आपका विशेष उद्देश्य क्या है। पायथन इंटरप्रेटर के विस्तार और एम्बेडिंग पर आधिकारिक पायथन प्रलेखन ऊपर उल्लेख किया गया था, मैं बाइनरी एक्सटेंशन का एक अच्छा अवलोकन जोड़ सकता हूं । उपयोग के मामलों को 3 श्रेणियों में विभाजित किया जा सकता है:

  • त्वरक मॉड्यूल : सीपीथॉन में चलने वाले बराबर शुद्ध पायथन कोड की तुलना में तेजी से चलाने के लिए।
  • आवरण मॉड्यूल : मौजूदा सी इंटरफेस को पायथन कोड में उजागर करना।
  • निम्न स्तर की प्रणाली पहुंच : CPython रनटाइम, ऑपरेटिंग सिस्टम या अंतर्निहित हार्डवेयर की निम्न स्तर की सुविधाओं का उपयोग करने के लिए।

अन्य इच्छुक लोगों के लिए कुछ व्यापक परिप्रेक्ष्य देने के लिए और चूंकि आपका प्रारंभिक प्रश्न थोड़ा अस्पष्ट है ("एक सी या सी ++ लाइब्रेरी के लिए") मुझे लगता है कि यह जानकारी आपके लिए दिलचस्प हो सकती है। ऊपर दिए गए लिंक पर आप बाइनरी एक्सटेंशन और इसके विकल्प का उपयोग करने के नुकसान पर पढ़ सकते हैं।

सुझाए गए अन्य उत्तरों के अलावा, यदि आप एक त्वरक मॉड्यूल चाहते हैं, तो आप नंबा की कोशिश कर सकते हैं । यह "आयात समय, रनटाइम, या स्टेटिकली (शामिल पाइक टूल का उपयोग करके) में एलएलवीएम कंपाइलर इंफ्रास्ट्रक्चर का उपयोग करके अनुकूलित मशीन कोड उत्पन्न करके काम करता है"।


2

मुझे दुःख बहुत पसंद है, यह पायथन को सी ++ कोड के साथ विस्तारित करना बहुत आसान बनाता है, जब जरूरत होती है तो नाटकीय रूप से प्रदर्शन बढ़ाता है।

यह शक्तिशाली और स्पष्ट रूप से उपयोग करने के लिए बहुत सरल है,

यहाँ यह एक उदाहरण है कि आप कैसे एक संख्यात्मक सारणी बना सकते हैं और इसे C ++ में एक क्लास मेंबर फंक्शन में पास कर सकते हैं।

import cppyy
cppyy.add_include_path("include")
cppyy.include('mylib/Buffer.h')


s = cppyy.gbl.buffer.Buffer()
numpy_array = np.empty(32000, np.float64)
s.get_numpy_array(numpy_array.data, numpy_array.size)

C ++ में:

struct Buffer {
  void get_numpy_array(int beam, double *ad, int size) {
    // fill the array
  }
}

आप बहुत आसानी से (CMake के साथ) एक Python मॉड्यूल भी बना सकते हैं, इस तरह आप हर समय C ++ कोड को फिर से जमा करने से बचेंगे।


1

pybind11 न्यूनतम रननीय उदाहरण

pybind11 को पहले https://stackoverflow.com/a/38542539/895245 पर उल्लेख किया गया था, लेकिन मैं यहां एक ठोस उपयोग उदाहरण देना चाहता हूं और कार्यान्वयन के बारे में कुछ और चर्चा करना चाहता हूं।

सभी और सभी, मैं अत्यधिक pybind11 की सलाह देता हूं क्योंकि इसका उपयोग करना वास्तव में आसान है: आप बस एक हेडर शामिल करते हैं और फिर pybind11 टेम्पलेट जादू का उपयोग करता है ताकि आप C ++ वर्ग का निरीक्षण कर सकें जिसे आप पायथन को उजागर करना चाहते हैं और जो पारदर्शी तरीके से करता है।

इस टेम्प्लेट मैजिक का नकारात्मक पक्ष यह है कि यह संकलन को धीमा कर देता है, जो कि pybind11 का उपयोग करने वाली किसी भी फ़ाइल में कुछ सेकंड जोड़ देता है, उदाहरण के लिए इस मुद्दे पर की गई जांच देखें । PyTorch सहमत हैं

यहाँ एक न्यूनतम चल उदाहरण है जो आपको यह महसूस करने के लिए देता है कि pybind11 कितना भयानक है:

class_test.cpp

#include <string>

#include <pybind11/pybind11.h>

struct ClassTest {
    ClassTest(const std::string &name) : name(name) { }
    void setName(const std::string &name_) { name = name_; }
    const std::string &getName() const { return name; }
    std::string name;
};

namespace py = pybind11;

PYBIND11_PLUGIN(class_test) {
    py::module m("my_module", "pybind11 example plugin");
    py::class_<ClassTest>(m, "ClassTest")
        .def(py::init<const std::string &>())
        .def("setName", &ClassTest::setName)
        .def("getName", &ClassTest::getName)
        .def_readwrite("name", &ClassTest::name);
    return m.ptr();
}

class_test_main.py

#!/usr/bin/env python3

import class_test

my_class_test = class_test.ClassTest("abc");
print(my_class_test.getName())
my_class_test.setName("012")
print(my_class_test.getName())
assert(my_class_test.getName() == my_class_test.name)

संकलित करें और चलाएं:

#!/usr/bin/env bash
set -eux
g++ `python3-config --cflags` -shared -std=c++11 -fPIC class_test.cpp \
  -o class_test`python3-config --extension-suffix` `python3-config --libs`
./class_test_main.py

यह उदाहरण दिखाता है कि कैसे pybind11 आपको आसानी ClassTestसे पायथन को C ++ वर्ग को उजागर करने की अनुमति देता है ! संकलन एक फ़ाइल का नाम देता है class_test.cpython-36m-x86_64-linux-gnu.soजो class_test_main.pyस्वचालित रूप से के लिए परिभाषा बिंदु के रूप में चुनता हैclass_test मूल रूप से परिभाषित मॉड्यूल के ।

शायद यह कितना भयानक है कि यह केवल डूब जाता है यदि आप मूल पायथन एपीआई के साथ हाथ से एक ही काम करने की कोशिश करते हैं, तो उदाहरण के लिए देखें कि ऐसा करने का उदाहरण, जिसमें लगभग 10x अधिक कोड है: https://github.com /cirosantilli/python-cheat/blob/4f676f62e87810582ad53b2fb426b74eae52aad5/py_from_c/pure.c इस उदाहरण से आप देख सकते हैं कि कैसे C कोड को दर्दनाक और स्पष्ट रूप से सभी जानकारी के साथ बिट जानकारी के साथ पाइथन वर्ग बिट को परिभाषित करना है। मेटाडाटा ...)। यह सभी देखें:

pybind11 उसी तरह होने का दावा करता है, Boost.Pythonजिसका उल्लेख https://stackoverflow.com/a/145436/895245 पर किया गया था, लेकिन अधिक न्यूनतम होने के कारण यह बूस्ट परियोजना के अंदर होने के प्रकोप से मुक्त होता है:

pybind11 एक लाइटवेट हेडर-ओनली लाइब्रेरी है जो पायथन में C ++ प्रकारों को उजागर करता है और इसके विपरीत, मुख्य रूप से मौजूदा C ++ कोड के पायथन बाइंडिंग बनाने के लिए। इसके लक्ष्य और वाक्यविन्यास डेविड अब्राहम द्वारा उत्कृष्ट Boost.Python पुस्तकालय के समान हैं: संकलन-समय आत्मनिरीक्षण का उपयोग करके प्रकार की जानकारी को संदर्भित करके पारंपरिक विस्तार मॉड्यूल में बॉयलरप्लेट कोड को कम करना।

Boost.Python के साथ मुख्य मुद्दा- और इस तरह की परियोजना को बनाने का कारण Boost है। बूस्ट यूटिलिटी लाइब्रेरी का एक बहुत बड़ा और जटिल सूट है जो अस्तित्व में लगभग हर C ++ कंपाइलर के साथ काम करता है। इस संगतता की अपनी लागत है: संकलक नमूनों के सबसे पुराने और बुग्गीस्ट का समर्थन करने के लिए आर्कैन टेम्पलेट ट्रिक्स और वर्कआर्ड्स आवश्यक हैं। अब जब C ++ 11-संगत कंपाइलर्स व्यापक रूप से उपलब्ध हैं, तो यह भारी मशीनरी अत्यधिक बड़े और अनावश्यक निर्भरता बन गई है।

इस लाइब्रेरी को Boost.Python के एक छोटे से स्व-निहित संस्करण के रूप में सोचें, जो हर उस चीज को छीन लेता है जो बाध्यकारी पीढ़ी के लिए प्रासंगिक नहीं है। टिप्पणियों के बिना, कोर हेडर फ़ाइलों को केवल कोड की ~ 4K लाइनों की आवश्यकता होती है और पायथन (2.7 या 3.x, या PyPy2.7> = 5.7) और C ++ मानक लाइब्रेरी पर निर्भर करती है। यह कॉम्पैक्ट कार्यान्वयन कुछ नई सी ++ 11 भाषा सुविधाओं (विशेष रूप से: ट्यूपल्स, लैम्ब्डा फ़ंक्शन और वेरिएड टेम्प्लेट) के लिए संभव था। अपने निर्माण के बाद से, यह पुस्तकालय कई मायनों में Boost.Python से आगे बढ़ गया है, जिससे कई सामान्य स्थितियों में नाटकीय रूप से सरल बाध्यकारी कोड हो गया है।

pybind11 वर्तमान Microsoft Python C बाइंडिंग दस्तावेज़ द्वारा केवल गैर-देशी वैकल्पिक hightlighted है: https://docs.microsoft.com/en-us/visualstudio/python/working-with-c-cpp-python-in दृश्य-स्टूडियो; दृश्य = बनाम 2019 ( संग्रह )।

उबंटू 18.04, pybind11 2.0.1, पायथन 3.6.8, जीसीसी 7.4.0 पर परीक्षण किया गया।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.