Gọi C / C ++ từ Python?


521

Điều gì sẽ là cách nhanh nhất để xây dựng một ràng buộc Python vào thư viện C hoặc C ++?

(Tôi đang sử dụng Windows nếu vấn đề này.)

Câu trả lời:


170

Bạn nên xem Boost.Python . Đây là phần giới thiệu ngắn được lấy từ trang web của họ:

Thư viện Python Python là một khung để giao tiếp với Python và C ++. Nó cho phép bạn hiển thị nhanh chóng và liền mạch các hàm và đối tượng của lớp C ++ cho Python và ngược lại, không sử dụng công cụ đặc biệt nào - chỉ là trình biên dịch C ++ của bạn. Nó được thiết kế để bao bọc các giao diện C ++ không xâm phạm, do đó bạn không cần phải thay đổi mã C ++ để bọc nó, làm cho Boost.Python trở nên lý tưởng để hiển thị các thư viện của bên thứ 3 cho Python. Việc thư viện sử dụng các kỹ thuật siêu lập trình nâng cao giúp đơn giản hóa cú pháp của nó cho người dùng, do đó, mã gói sẽ mang dáng dấp của một loại ngôn ngữ định nghĩa giao diện khai báo (IDL).


Boost.Python là một trong những thư viện thân thiện với người dùng hơn trong Boost, đối với một hàm gọi API đơn giản, nó khá đơn giản và cung cấp bản tóm tắt mà bạn phải tự viết. Sẽ phức tạp hơn một chút nếu bạn muốn trưng ra API hướng đối tượng.
jwfearn

15
Boost.Python là điều tồi tệ nhất có thể tưởng tượng. Đối với mỗi máy mới và với mỗi lần nâng cấp, nó đi kèm với các vấn đề liên kết.
cối xay

14
Gần 11 năm sau thời gian để suy ngẫm về chất lượng của câu trả lời này?
J Evans

4
Đây có phải vẫn là cách tiếp cận tốt nhất để giao diện python và c ++?
tushaR

8
Có lẽ bạn có thể thử pybind11 nhẹ hơn so với boost.
jdhao

659

ctypes Module này là một phần của thư viện chuẩn, và do đó là ổn định và phổ biến rộng rãi hơn uống một lân , mà luôn luôn có xu hướng để cho tôi vấn đề .

Với ctypes, bạn cần đáp ứng bất kỳ sự phụ thuộc thời gian biên dịch nào vào python và ràng buộc của bạn sẽ hoạt động trên bất kỳ python nào có ctypes, không chỉ là cái mà nó được biên dịch.

Giả sử bạn có một lớp ví dụ C ++ đơn giản mà bạn muốn nói chuyện trong một tệp có tên foo.cpp:

#include <iostream>

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

Vì ctypes chỉ có thể nói chuyện với các hàm C, nên bạn cần cung cấp cho những người khai báo chúng là "C" bên ngoài

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

Tiếp theo, bạn phải biên dịch nó vào một thư viện chia sẻ

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

Và cuối cùng, bạn phải viết trình bao bọc python của bạn (ví dụ: trong 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)

Một khi bạn có mà bạn có thể gọi nó như

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

14
Đây là khá nhiều những gì boost.python làm cho bạn trong một cuộc gọi chức năng.
Martin Beckett

203
ctypes nằm trong thư viện chuẩn python, swig và boost thì không. Swig và boost dựa vào các mô-đun mở rộng và do đó được gắn với các phiên bản nhỏ của python mà các đối tượng chia sẻ độc lập thì không. xây dựng một swig hoặc boost Wrappers có thể là một nỗi đau, ctypes không yêu cầu xây dựng.
Florian Bösch

25
boost dựa vào ma thuật mẫu voodoo và một hệ thống xây dựng hoàn toàn tùy chỉnh, ctypes dựa vào sự đơn giản. ctypes là động, tăng là tĩnh. ctypes có thể xử lý các phiên bản khác nhau của thư viện. tăng không thể.
Florian Bösch

32
Trên Windows, tôi đã phải chỉ định __declspec (dllexport) trong chữ ký hàm của mình để Python có thể nhìn thấy chúng. Từ ví dụ trên, điều này sẽ tương ứng với: extern "C" { __declspec(dllexport) Foo* Foo_new(){ return new Foo(); } __declspec(dllexport) void Foo_bar(Foo* foo){ foo->bar(); } }
Alan Macdonald

13
Đừng quên xóa con trỏ sau đó bằng cách cung cấp một Foo_deletehàm và gọi nó từ một hàm hủy python hoặc bọc đối tượng trong một tài nguyên .
Adversus 04/11/2015

58

Cách nhanh nhất để làm điều này là sử dụng SWIG .

Ví dụ từ hướng dẫn SWIG :

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

Tệp giao diện:

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

extern int fact(int n);

Xây dựng mô-đun Python trên Unix:

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

Sử dụng:

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

Lưu ý rằng bạn phải có python-dev. Ngoài ra, trong một số hệ thống, các tệp tiêu đề python sẽ nằm trong /usr/include/python2.7 dựa trên cách bạn đã cài đặt nó.

Từ hướng dẫn:

SWIG là một trình biên dịch C ++ khá hoàn chỉnh với sự hỗ trợ cho gần như mọi tính năng ngôn ngữ. Điều này bao gồm tiền xử lý, con trỏ, lớp, kế thừa và thậm chí các mẫu C ++. SWIG cũng có thể được sử dụng để đóng gói các cấu trúc và các lớp thành các lớp proxy theo ngôn ngữ đích - phơi bày các chức năng cơ bản theo cách rất tự nhiên.


50

Tôi bắt đầu hành trình của mình trong liên kết Python <-> C ++ từ trang này, với mục tiêu liên kết các loại dữ liệu cấp cao (vectơ STL đa chiều với danh sách Python) :-)

Đã thử các giải pháp dựa trên cả ctypesboost.python (và không phải là kỹ sư phần mềm), tôi thấy chúng phức tạp khi yêu cầu liên kết kiểu dữ liệu mức cao, trong khi tôi thấy SWIG đơn giản hơn nhiều cho các trường hợp như vậy.

Do đó, ví dụ này sử dụng SWIG và nó đã được thử nghiệm trong Linux (nhưng SWIG có sẵn và cũng được sử dụng rộng rãi trong Windows).

Mục tiêu là làm cho hàm C ++ có sẵn cho Python lấy ma trận dưới dạng vectơ STL 2D và trả về trung bình của mỗi hàng (dưới dạng vectơ STL 1D).

Mã trong C ++ ("code.cpp") như sau:

#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;
}

Tiêu đề tương đương ("code.h") là:

#ifndef _code
#define _code

#include <vector>

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

#endif

Trước tiên chúng tôi biên dịch mã C ++ để tạo tệp đối tượng:

g++ -c -fPIC code.cpp

Sau đó, chúng tôi xác định tệp định nghĩa giao diện SWIG ("code.i") cho các hàm C ++ của chúng tô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"

Sử dụng SWIG, chúng tôi tạo mã nguồn giao diện C ++ từ tệp định nghĩa giao diện SWIG ..

swig -c++ -python code.i

Cuối cùng chúng tôi đã biên dịch tệp nguồn giao diện C ++ đã tạo và liên kết mọi thứ lại với nhau để tạo thư viện dùng chung mà Python có thể nhập trực tiếp (vấn đề "_"):

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

Bây giờ chúng ta có thể sử dụng hàm trong các tập lệnh Python:

#!/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

Một triển khai trường hợp thực tế trong đó các vectơ stl mã C ++ được truyền dưới dạng tham chiếu không const và do đó có sẵn bởi python làm tham số đầu ra: lobianco.org/antonello/personal:port portfolio
Antonello

33

Ngoài ra pybind11, nó cũng giống như một phiên bản nhẹ của Boost.Python và tương thích với tất cả các trình biên dịch C ++ hiện đại:

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


1
Hôm nay !! 2020 Đây phải là câu trả lời hàng đầu! Nó là một thư viện mẫu tiêu đề duy nhất. Nhiều dự án lớn có liên quan đề xuất nó, như Pytorch pytorch.org/tutorials/advified/cpp_extension.html Cũng hoạt động đầy đủ trên VS CommunityWindows
eusoubrasileiro

30

Kiểm tra pyrex hoặc Cython . Chúng là các ngôn ngữ giống như Python để giao tiếp giữa C / C ++ và Python.


1
+1 cho Cython! Tôi chưa thử cffi vì vậy tôi không thể nói cái nào tốt hơn, nhưng tôi đã có những trải nghiệm rất tốt với Cython - bạn vẫn đang viết mã Python nhưng bạn có thể sử dụng C trong đó. Tôi hơi khó khăn khi thiết lập quy trình xây dựng với Cython, mà sau này tôi đã giải thích trong một bài đăng trên blog: martinsosic.com/development/2016/02/08/ trộm
Martinsos

Bạn có thể muốn cải thiện câu trả lời để không còn là câu trả lời chỉ liên kết.
Adelin

Tôi đã sử dụng Cython được khoảng một tuần và tôi rất thích nó: 1) Tôi đã thấy ctypes đang sử dụng và nó rất UGLY và rất dễ bị lỗi với nhiều cạm bẫy 2) Nó cho phép bạn lấy một số mã Python và tăng tốc nó từ việc gõ tĩnh mọi thứ một mình 3) Thật đơn giản để viết các hàm bao Python cho các phương thức và đối tượng C / C ++ 4) Nó vẫn được hỗ trợ tốt. Nó có thể làm với việc hướng dẫn cài đặt vis-a-vis nhiều hơn cho venvs và biên dịch chéo, việc này đã mất một chút thời gian để xử lý. Có một video hướng dẫn 4 giờ rất hay ở đây: youtube.com/watch?v=gMvkiQ-gOW8
Den-Jason

22

Đối với C ++ hiện đại, hãy sử dụng cppyy: http://cppyy.readthedocs.io/en/latest/

Nó dựa trên Cling, trình thông dịch C ++ cho Clang / LLVM. Các ràng buộc đang trong thời gian chạy và không cần thêm ngôn ngữ trung gian. Nhờ Clang, nó hỗ trợ C ++ 17.

Cài đặt nó bằng pip:

    $ pip install cppyy

Đối với các dự án nhỏ, chỉ cần tải thư viện có liên quan và các tiêu đề mà bạn quan tâm. Ví dụ: lấy mã từ ví dụ ctypes là luồng này, nhưng phân chia trong phần tiêu đề và mã:

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

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

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

Biên dịch nó:

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

và sử dụng nó:

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

Các dự án lớn được hỗ trợ tự động tải thông tin phản ánh đã chuẩn bị và các đoạn cmake để tạo chúng, để người dùng các gói đã cài đặt có thể chạy đơn giản:

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

Nhờ LLVM, các tính năng nâng cao là có thể, chẳng hạn như khởi tạo mẫu tự động. Để tiếp tục ví dụ:

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

Lưu ý: Tôi là tác giả của cppyy.


3
Thực sự không phải vậy: Cython là ngôn ngữ lập trình giống như Python để viết các mô đun mở rộng C cho Python (mã Cython được dịch sang C, cùng với bản tóm tắt C-API cần thiết). Nó cung cấp một số hỗ trợ C ++ cơ bản. Lập trình với cppyy chỉ liên quan đến Python và C ++, không có phần mở rộng ngôn ngữ. Đó là thời gian chạy hoàn toàn và không tạo mã ngoại tuyến (thế hệ lười biếng quy mô tốt hơn rất nhiều). Nó nhắm mục tiêu C ++ hiện đại (bao gồm khởi tạo mẫu tự động, di chuyển, initizer_lists, lambda, v.v.) và PyPy được hỗ trợ nguyên bản (tức là không thông qua lớp mô phỏng C-API chậm).
Wim Lavrijsen

2
Bài viết này của PyHPC'16 chứa một loạt các số chuẩn. Kể từ đó, đã có những cải tiến nhất định về phía CPython.
Wim Lavrijsen

Tôi thích cách tiếp cận này bởi vì bạn không cần phải làm việc tích hợp thêm với swig, ctypeshoặc boost.python. Thay vì bạn phải viết mã để python hoạt động với mã c ++ của bạn ... python thực hiện công việc khó khăn để tìm ra c ++. Giả sử nó thực sự hoạt động.
Trevor Boyd Smith

cppyy là rất thú vị! Tôi thấy trong các tài liệu rằng phân phối lại và đóng gói trước được xử lý. Điều này có được biết là hoạt động tốt với các công cụ đóng gói mã python không (ví dụ: PyInstaller)? Và điều này có liên quan đến dự án ROOT, hay tận dụng công việc của nó không?
JimB

Cảm ơn! Tôi không quen thuộc với PyInstaller, nhưng "từ điển" đóng gói các khai báo, đường dẫn và tiêu đề chuyển tiếp là các mã C ++ được biên dịch thành các lib được chia sẻ. Vì cppyy được sử dụng để liên kết mã C ++, tôi cho rằng việc xử lý một số mã C ++ khác sẽ ổn. Và mã đó không phụ thuộc vào Python C-API (chỉ có mô-đun libcppyy), giúp đơn giản hóa mọi thứ. cppyy có thể được cài đặt từ conda-forge hoặc pypi (pip), do đó, bất kỳ môi trường nào trong số đó hoạt động, chắc chắn. Vâng, cppyy bắt đầu như một ngã ba từ PyROOT, nhưng nó đã được cải thiện rất nhiều, rằng nhóm ROOT đang nổi loạn PyROOT trên đỉnh của cppyy.
Wim Lavrijsen


15

Tôi chưa bao giờ sử dụng nó nhưng tôi đã nghe những điều tốt về ctypes . Nếu bạn đang cố gắng sử dụng nó với C ++, hãy nhớ tránh xáo trộn tên extern "C". Cảm ơn vì nhận xét, Florian Bösch.


13

Tôi nghĩ rằng cffi cho python có thể là một lựa chọn.

Mục tiêu là gọi mã C từ Python. Bạn sẽ có thể làm như vậy mà không cần học ngôn ngữ thứ 3: mọi phương án đều yêu cầu bạn phải học ngôn ngữ của riêng họ (Cython, SWIG) hoặc API (ctypes). Vì vậy, chúng tôi đã cố gắng giả định rằng bạn biết Python và C và giảm thiểu các bit API bổ sung mà bạn cần tìm hiểu.

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


2
Tôi nghĩ rằng điều này chỉ có thể gọi c (không phải c ++), vẫn là +1 (tôi thực sự thích cffi).
Andy Hayden

8

Câu hỏi là làm thế nào để gọi hàm C từ Python, nếu tôi hiểu đúng. Sau đó, đặt cược tốt nhất là Ctypes (BTW di động trên tất cả các biến thể của Python).

>>> 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

Để được hướng dẫn chi tiết, bạn có thể muốn tham khảo bài viết trên blog của tôi .


Có thể đáng lưu ý rằng trong khi ctypes là di động, mã của bạn yêu cầu thư viện C dành riêng cho Windows.
Palec


6

Cython chắc chắn là con đường để đi, trừ khi bạn dự đoán việc viết các trình bao bọc Java, trong trường hợp đó SWIG có thể thích hợp hơn.

Tôi khuyên bạn nên sử dụng runcythontiện ích dòng lệnh, nó làm cho quá trình sử dụng Cython cực kỳ dễ dàng. Nếu bạn cần chuyển dữ liệu có cấu trúc sang C ++, hãy xem thư viện protobuf của Google, điều đó rất thuận tiện.

Đây là một ví dụ tối thiểu tôi đã sử dụng cả hai công cụ:

https://github.com/nicodjimenez/python2cpp

Hy vọng nó có thể là một điểm khởi đầu hữu ích.


5

Trước tiên, bạn nên quyết định mục đích cụ thể của bạn là gì. Tài liệu Python chính thức về mở rộng và nhúng trình thông dịch Python đã được đề cập ở trên, tôi có thể thêm một tổng quan tốt về các phần mở rộng nhị phân . Các trường hợp sử dụng có thể được chia thành 3 loại:

  • mô đun máy gia tốc : để chạy nhanh hơn mã Python thuần tương đương chạy trong CPython.
  • mô-đun trình bao bọc : để hiển thị các giao diện C hiện có thành mã Python.
  • truy cập hệ thống cấp thấp : để truy cập các tính năng cấp thấp hơn của thời gian chạy CPython, hệ điều hành hoặc phần cứng cơ bản.

Để đưa ra một số quan điểm rộng hơn cho những người quan tâm khác và vì câu hỏi ban đầu của bạn hơi mơ hồ ("với thư viện C hoặc C ++") tôi nghĩ thông tin này có thể thú vị với bạn. Trên liên kết ở trên, bạn có thể đọc về những nhược điểm của việc sử dụng tiện ích mở rộng nhị phân và các lựa chọn thay thế.

Ngoài các câu trả lời khác được đề xuất, nếu bạn muốn một mô-đun tăng tốc, bạn có thể thử Numba . Nó hoạt động "bằng cách tạo mã máy được tối ưu hóa bằng cơ sở hạ tầng trình biên dịch LLVM tại thời điểm nhập, thời gian chạy hoặc tĩnh (sử dụng công cụ pycc đi kèm)".


3

Tôi yêu cppyy, nó giúp dễ dàng mở rộng Python bằng mã C ++, tăng đáng kể hiệu năng khi cần.

Nó rất mạnh mẽ và thực sự rất đơn giản để sử dụng,

đây là một ví dụ về cách bạn có thể tạo một mảng numpy và chuyển nó đến một hàm thành viên lớp trong C ++.

cppyy_test.py

import cppyy
import numpy as np
cppyy.include('Buffer.h')


s = cppyy.gbl.Buffer()
numpy_array = np.empty(32000, np.float64)
s.get_numpy_array(numpy_array.data, numpy_array.size)
print(numpy_array[:20])

Bộ đệm.h

struct Buffer {
  void get_numpy_array(double *ad, int size) {
    for( long i=0; i < size; i++)
        ad[i]=i;
  }
};

Bạn cũng có thể tạo mô-đun Python rất dễ dàng (với CMake), bằng cách này bạn sẽ tránh biên dịch lại mã C ++ mọi lúc.


2

pybind11 ví dụ runnable tối thiểu

pybind11 đã được đề cập trước đây tại https://stackoverflow.com/a/38542539/895245 nhưng tôi muốn đưa ra một ví dụ sử dụng cụ thể và một số thảo luận thêm về việc thực hiện.

Tất cả và tất cả, tôi đánh giá cao pybind11 vì nó rất dễ sử dụng: bạn chỉ cần bao gồm một tiêu đề và sau đó pybind11 sử dụng ma thuật mẫu để kiểm tra lớp C ++ mà bạn muốn tiếp xúc với Python và thực hiện điều đó một cách minh bạch.

Nhược điểm của phép thuật mẫu này là nó làm chậm quá trình biên dịch ngay lập tức thêm một vài giây vào bất kỳ tệp nào sử dụng pybind11, xem ví dụ điều tra được thực hiện về vấn đề này . PyTorch đồng ý .

Dưới đây là một ví dụ có thể chạy tối thiểu để cho bạn cảm giác về pybind11 tuyệt vời như thế nào:

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)

Biên dịch và chạy:

#!/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

Ví dụ này cho thấy pybind11 cho phép bạn dễ dàng hiển thị lớp ClassTestC ++ cho Python! Compilation tạo ra một file có tên class_test.cpython-36m-x86_64-linux-gnu.sođó class_test_main.pytự động nhặt như là điểm định nghĩa cho các class_testmô-đun natively xác định.

Có lẽ việc nhận ra điều này tuyệt vời như thế nào chỉ chìm trong nếu bạn cố gắng làm điều tương tự bằng tay với API Python nguyên bản, xem ví dụ về ví dụ này để làm điều đó, có thêm 10 lần mã: https://github.com /cirosantilli/python-cheat/blob/4f676f62e87810582ad53b2fb426b74eae52aad5/py_from_c/pure.c Trên ví dụ đó, bạn có thể thấy mã C phải xác định một cách đau đớn và rõ ràng như thế nào về mã Python. metadata...). Xem thêm:

pybind11 tuyên bố là tương tự như Boost.Pythonđã được đề cập tại https://stackoverflow.com/a/145436/895245 nhưng tối thiểu hơn vì nó được giải phóng khỏi sự phình to của bên trong dự án Boost:

pybind11 là một thư viện chỉ dành cho tiêu đề nhẹ, hiển thị các loại C ++ trong Python và ngược lại, chủ yếu để tạo các ràng buộc Python của mã C ++ hiện có. Mục tiêu và cú pháp của nó tương tự như thư viện Boost.Python tuyệt vời của David Abrahams: để giảm thiểu mã soạn sẵn trong các mô-đun mở rộng truyền thống bằng cách suy ra thông tin loại bằng cách sử dụng nội suy thời gian biên dịch.

Vấn đề chính với Boost.Python, và lý do để tạo ra một dự án tương tự như vậy là Boost. Boost là một bộ thư viện tiện ích rất lớn và phức tạp, hoạt động với hầu hết mọi trình biên dịch C ++ đang tồn tại. Khả năng tương thích này có chi phí của nó: các thủ thuật và giải pháp mẫu phức tạp là cần thiết để hỗ trợ các mẫu biên dịch lâu đời nhất và khó tính nhất. Giờ đây, trình biên dịch tương thích C ++ 11 đã có mặt rộng rãi, bộ máy hạng nặng này đã trở thành một sự phụ thuộc quá lớn và không cần thiết.

Hãy nghĩ về thư viện này như một phiên bản nhỏ của Boost.Python với mọi thứ bị loại bỏ không liên quan đến việc tạo ràng buộc. Không có nhận xét, các tệp tiêu đề lõi chỉ yêu cầu ~ dòng mã 4K và phụ thuộc vào Python (2.7 hoặc 3.x hoặc PyPy2.7> = 5.7) và thư viện chuẩn C ++. Việc triển khai nhỏ gọn này có thể thực hiện được nhờ một số tính năng ngôn ngữ mới của C ++ 11 (cụ thể: bộ dữ liệu, chức năng lambda và các mẫu biến đổi). Kể từ khi thành lập, thư viện này đã phát triển vượt xa Boost.Python theo nhiều cách, dẫn đến mã ràng buộc đơn giản hơn đáng kể trong nhiều tình huống phổ biến.

pybind11 cũng là sự thay thế không phải bản địa duy nhất được làm sáng tỏ bởi tài liệu ràng buộc Microsoft Python C hiện tại tại: https://docs.microsoft.com/en-us/visualstudio/python/usiness-with-c-cpp-python-in- visual-studio? view = vs-2019 ( lưu trữ ).

Đã thử nghiệm trên Ubuntu 18.04, pybind11 2.0.1, Python 3.6.8, GCC 7.4.0.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.