Memanggil C / C ++ dari Python?


521

Apa cara tercepat untuk membangun Python yang mengikat ke pustaka C atau C ++?

(Saya menggunakan Windows jika ini penting.)

Jawaban:


170

Anda harus melihat Boost.Python . Berikut adalah pengantar singkat yang diambil dari situs web mereka:

Perpustakaan Boost Python adalah kerangka kerja untuk menghubungkan Python dan C ++. Ini memungkinkan Anda untuk dengan cepat dan mulus mengekspos fungsi kelas C ++ dan objek ke Python, dan sebaliknya, tanpa menggunakan alat khusus - hanya kompiler C ++ Anda. Ini dirancang untuk membungkus antarmuka C ++ non-intrusively, sehingga Anda tidak perlu mengubah kode C ++ sama sekali untuk membungkusnya, membuat Boost.Python ideal untuk mengekspos perpustakaan pihak ke-3 ke Python. Penggunaan teknik metaprogramming tingkat lanjut dari perpustakaan menyederhanakan sintaksnya untuk pengguna, sehingga kode pembungkus terlihat seperti jenis bahasa definisi antarmuka deklaratif (IDL).


Boost.Python adalah salah satu pustaka yang lebih ramah pengguna di Boost, untuk API panggilan fungsi sederhana ini cukup mudah dan menyediakan boilerplate yang harus Anda tulis sendiri. Ini sedikit lebih rumit jika Anda ingin mengekspos API berorientasi objek.
jwfearn

15
Boost.Python adalah hal terburuk yang bisa dibayangkan. Untuk setiap mesin baru dan setiap pemutakhiran, ini terkait dengan masalah penautan.
miller

14
Hampir 11 tahun kemudian waktu untuk perenungan tentang kualitas jawaban ini?
J Evans

4
Apakah ini masih pendekatan terbaik untuk antarmuka python dan c ++?
tushaR

8
Mungkin Anda bisa mencoba pybind11 yang lebih ringan dibandingkan dengan boost.
jdhao

659

Modul ctypes adalah bagian dari library standar, dan karenanya lebih stabil dan tersedia secara luas daripada swig , yang selalu cenderung memberi saya masalah. .

Dengan ctypes, Anda harus memenuhi setiap dependensi waktu kompilasi pada python, dan pengikatan Anda akan bekerja pada python yang memiliki ctypes, bukan hanya kompilasi yang dikompilasi.

Misalkan Anda memiliki kelas contoh C ++ sederhana yang ingin Anda ajak bicara dalam file bernama foo.cpp:

#include <iostream>

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

Karena ctypes hanya dapat berbicara dengan fungsi C, Anda perlu menyediakan yang menyatakannya sebagai "C" dari luar

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

Selanjutnya Anda harus mengkompilasi ini ke perpustakaan bersama

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

Dan akhirnya Anda harus menulis pembungkus python Anda (misalnya di 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)

Setelah Anda memilikinya Anda dapat menyebutnya seperti

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

14
Ini adalah apa yang boost.python lakukan untuk Anda dalam satu panggilan fungsi.
Martin Beckett

203
ctypes ada di pustaka standar python, swig dan boost tidak. Meneguk dan meningkatkan bergantung pada modul ekstensi dan oleh karena itu terikat ke versi minor python yang tidak berbagi objek independen. membangun tegukan atau meningkatkan pembungkus bisa jadi menyebalkan, ctypes tidak membuat persyaratan apa pun.
Florian Bösch

25
boost bergantung pada magic template voodoo dan sistem build yang sepenuhnya custom, ctypes bergantung pada kesederhanaan. ctypes dinamis, boost statis. ctypes dapat menangani berbagai versi perpustakaan. meningkatkan tidak bisa.
Florian Bösch

32
Pada Windows saya harus menentukan __declspec (dllexport) dalam fungsi tanda tangan saya agar Python dapat melihatnya. Dari contoh di atas ini akan sesuai dengan: extern "C" { __declspec(dllexport) Foo* Foo_new(){ return new Foo(); } __declspec(dllexport) void Foo_bar(Foo* foo){ foo->bar(); } }
Alan Macdonald

13
Jangan lupa untuk menghapus pointer setelah itu dengan misalnya menyediakan Foo_deletefungsi dan memanggilnya baik dari penghancur python atau membungkus objek dalam sumber daya .
Adversus

58

Cara tercepat untuk melakukan ini adalah menggunakan SWIG .

Contoh dari tutorial SWIG :

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

File antarmuka:

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

extern int fact(int n);

Membangun modul Python di 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

Pemakaian:

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

Perhatikan bahwa Anda harus memiliki python-dev. Juga di beberapa sistem file header python akan berada di /usr/include/python2.7 berdasarkan cara Anda menginstalnya.

Dari tutorial:

SWIG adalah kompiler C ++ yang cukup lengkap dengan dukungan untuk hampir setiap fitur bahasa. Ini termasuk preprocessing, pointer, kelas, warisan, dan bahkan template C ++. SWIG juga dapat digunakan untuk mengemas struktur dan kelas menjadi kelas proksi dalam bahasa target - mengekspos fungsi yang mendasarinya dengan cara yang sangat alami.


50

Saya memulai perjalanan saya di Python <-> C ++ mengikat dari halaman ini, dengan tujuan menghubungkan tipe data tingkat tinggi (vektor STL multidimensi dengan daftar Python) :-)

Setelah mencoba solusi berdasarkan ctypes dan boost.python (dan tidak menjadi insinyur perangkat lunak) saya telah menemukan mereka kompleks ketika diperlukan mengikat tipe data tingkat tinggi, sementara saya telah menemukan SWIG jauh lebih sederhana untuk kasus-kasus seperti itu.

Oleh karena itu, contoh ini menggunakan SWIG, dan telah diuji di Linux (tetapi SWIG tersedia dan banyak digunakan di Windows juga).

Tujuannya adalah untuk membuat fungsi C ++ tersedia untuk Python yang mengambil matriks dalam bentuk vektor STL 2D dan mengembalikan rata-rata setiap baris (sebagai vektor 1D STL).

Kode dalam C ++ ("code.cpp") adalah sebagai berikut:

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

Header yang setara ("code.h") adalah:

#ifndef _code
#define _code

#include <vector>

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

#endif

Kami pertama-tama mengkompilasi kode C ++ untuk membuat file objek:

g++ -c -fPIC code.cpp

Kami kemudian mendefinisikan file definisi antarmuka SWIG ("code.i") untuk fungsi C ++ kami.

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

Menggunakan SWIG, kami membuat kode sumber antarmuka C ++ dari file definisi antarmuka SWIG ..

swig -c++ -python code.i

Kami akhirnya mengkompilasi file sumber antarmuka C ++ yang dihasilkan dan menautkan semuanya untuk menghasilkan pustaka bersama yang secara langsung dapat diimpor oleh Python (hal-hal "_"):

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

Kita sekarang dapat menggunakan fungsi dalam skrip 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

Implementasi kasus nyata di mana dalam kode C ++ stl vektor dilewatkan sebagai referensi non const dan karenanya tersedia dengan python sebagai parameter output: lobianco.org/antonello/personal:portfolio:portopt
Antonello


30

Lihat pyrex atau Cython . Mereka adalah bahasa seperti Python untuk antarmuka antara C / C ++ dan Python.


1
+1 untuk Cython! Saya belum mencoba cffi jadi saya tidak bisa mengatakan mana yang lebih baik, tetapi saya memiliki pengalaman yang sangat baik dengan Cython - Anda masih menulis kode Python tetapi Anda dapat menggunakan C di dalamnya. Agak sulit bagi saya untuk mengatur proses pembuatan dengan Cython, yang kemudian saya jelaskan dalam posting blog: martinsosic.com/development/2016/02/08/...
Martinsos

Anda mungkin ingin meningkatkan jawaban agar tidak lagi menjadi jawaban tautan saja.
Adelin

Saya telah menggunakan Cython selama sekitar satu minggu dan saya sangat menyukainya: 1) Saya telah melihat ctypes sedang digunakan dan itu adalah UGLY dan sangat rawan kesalahan dengan banyak jebakan 2) Ini memungkinkan Anda untuk mengambil beberapa kode Python dan mempercepatnya dari mengetik secara statis saja 3) Sangat mudah untuk menulis pembungkus Python untuk metode dan objek C / C ++ 4) Masih didukung dengan baik. Ini bisa dilakukan dengan lebih banyak panduan vis-a-vis menginstal ke venvs dan cross-compiling, yang telah mengambil sedikit waktu untuk menyelesaikannya. Ada tutorial video 4 jam yang sangat bagus di sini: youtube.com/watch?v=gMvkiQ-gOW8
Den-Jason

22

Untuk C ++ modern, gunakan cppyy: http://cppyy.readthedocs.io/en/latest/

Ini berdasarkan Cling, juru bahasa C ++ untuk Dentang / LLVM. Binding pada saat run-time dan tidak ada bahasa perantara tambahan yang diperlukan. Berkat Dentang, ini mendukung C ++ 17.

Instal menggunakan pip:

    $ pip install cppyy

Untuk proyek-proyek kecil, cukup muat pustaka yang relevan dan tajuk yang Anda minati. Misalnya ambil kode dari ctypes contohnya adalah utas ini, tetapi bagi bagian header dan kode:

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

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

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

Kompilasi:

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

dan gunakan:

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

Proyek besar didukung dengan pemuatan otomatis informasi refleksi yang disiapkan dan fragmen cmake untuk membuatnya, sehingga pengguna paket yang diinstal dapat dengan mudah menjalankan:

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

Berkat LLVM, fitur-fitur canggih dimungkinkan, seperti contoh template otomatis. Untuk melanjutkan contoh:

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

Catatan: Saya penulis cppyy.


3
Sebenarnya tidak: Cython adalah bahasa pemrograman mirip-Python untuk menulis modul ekstensi C untuk Python (kode Cython akan diterjemahkan ke dalam C, bersama dengan boilerplate C-API yang diperlukan). Ini memberikan beberapa dukungan dasar C ++. Pemrograman dengan cppyy hanya melibatkan Python dan C ++, tanpa ekstensi bahasa. Ini sepenuhnya dijalankan-waktu dan tidak menghasilkan kode offline (generasi malas skala jauh lebih baik). Ini menargetkan C ++ modern (termasuk contoh template otomatis, bergerak, initializer_lists, lambda, dll., Dll) dan PyPy didukung secara native (yaitu tidak melalui lapisan emulasi C-API lambat).
Wim Lavrijsen

2
Makalah PyHPC'16 ini berisi berbagai nomor patokan. Sejak itu, ada perbaikan yang pasti di sisi CPython.
Wim Lavrijsen

Saya suka pendekatan ini karena Anda tidak harus melakukan pekerjaan integrasi tambahan swig, ctypesatau boost.python. Alih-alih Anda harus menulis kode untuk membuat python bekerja dengan kode c ++ Anda ... python bekerja keras untuk mencari tahu c ++. Dengan asumsi itu benar-benar berfungsi.
Trevor Boyd Smith

cppyy sangat menarik! Saya melihat dalam dokumen bahwa redistribusi dan pra-pengemasan ditangani. Apakah ini diketahui bekerja dengan baik dengan alat yang mengemas kode python juga (misalnya, PyInstaller)? Dan apakah ini terkait dengan proyek ROOT, atau memanfaatkan pekerjaannya?
JimB

Terima kasih! Saya tidak terbiasa dengan PyInstaller, tetapi "kamus" yang mengemas deklarasi maju, path, dan header adalah kode C ++ yang dikompilasi untuk lib bersama. Karena cppyy digunakan untuk mengikat kode C ++, saya kira menangani lebih banyak kode C ++ harus baik-baik saja. Dan kode itu tidak tergantung pada Python C-API (hanya modul libcppyy), yang menyederhanakan banyak hal. cppyy sendiri dapat diinstal dari conda-forge atau pypi (pip), jadi salah satu dari lingkungan tersebut berfungsi, pasti. Ya, cppyy dimulai sebagai garpu dari PyROOT, tetapi sejak itu telah meningkat banyak, bahwa tim ROOT rebasing PyROOT di atas cppyy.
Wim Lavrijsen


15

Saya tidak pernah menggunakannya tetapi saya pernah mendengar hal-hal baik tentang ctypes . Jika Anda mencoba menggunakannya dengan C ++, pastikan untuk menghindari pengubahan nama via extern "C". Terima kasih atas komentarnya, Florian Bösch.


13

Saya pikir cffi untuk python dapat menjadi pilihan.

Tujuannya adalah untuk memanggil kode C dari Python. Anda harus dapat melakukannya tanpa mempelajari bahasa ketiga: setiap alternatif mengharuskan Anda mempelajari bahasa mereka sendiri (Cython, SWIG) atau API (ctypes). Jadi kami mencoba berasumsi bahwa Anda tahu Python dan C dan meminimalkan bit tambahan API yang perlu Anda pelajari.

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


2
Saya pikir ini hanya dapat memanggil c (bukan c ++), masih +1 (saya sangat suka cffi).
Andy Hayden

8

Pertanyaannya adalah bagaimana memanggil fungsi C dari Python, jika saya mengerti dengan benar. Maka taruhan terbaik adalah Ctypes (BTW portable di semua varian 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

Untuk panduan terperinci Anda mungkin ingin merujuk ke artikel blog saya .


Mungkin perlu dicatat bahwa sementara ctypes bersifat portable, kode Anda memerlukan pustaka C khusus Windows.
Palec


6

Cython jelas merupakan cara yang harus ditempuh, kecuali Anda mengantisipasi penulisan pembungkus Java, dalam hal ini SWIG mungkin lebih disukai.

Saya sarankan menggunakan runcythonutilitas baris perintah, itu membuat proses menggunakan Cython sangat mudah. Jika Anda perlu mengirimkan data terstruktur ke C ++, lihat perpustakaan protobuf Google, itu sangat nyaman.

Berikut adalah contoh minimal yang saya buat yang menggunakan kedua alat:

https://github.com/nicodjimenez/python2cpp

Semoga ini bisa menjadi titik awal yang bermanfaat.


5

Pertama, Anda harus memutuskan apa tujuan khusus Anda. Dokumentasi Python resmi tentang memperluas dan menanamkan interpreter Python telah disebutkan di atas, saya dapat menambahkan ikhtisar yang baik tentang ekstensi biner . Kasus penggunaan dapat dibagi menjadi 3 kategori:

  • modul akselerator : untuk berjalan lebih cepat daripada kode Python murni yang setara berjalan di CPython.
  • modul wrapper : untuk mengekspos antarmuka C yang ada ke kode Python.
  • akses sistem level rendah : untuk mengakses fitur level rendah dari runtime CPython, sistem operasi, atau perangkat keras yang mendasarinya.

Untuk memberikan perspektif yang lebih luas bagi orang lain yang tertarik dan karena pertanyaan awal Anda agak kabur ("ke perpustakaan C atau C ++"), saya pikir informasi ini mungkin menarik bagi Anda. Pada tautan di atas Anda dapat membaca tentang kerugian menggunakan ekstensi biner dan alternatifnya.

Terlepas dari jawaban lain yang disarankan, jika Anda menginginkan modul akselerator, Anda dapat mencoba Numba . Ia bekerja "dengan menghasilkan kode mesin yang dioptimalkan menggunakan infrastruktur kompiler LLVM pada waktu impor, runtime, atau secara statis (menggunakan alat pycc yang disertakan)".


3

Saya suka cppyy, membuatnya sangat mudah untuk memperpanjang Python dengan kode C ++, secara dramatis meningkatkan kinerja saat dibutuhkan.

Ini kuat dan terus terang sangat mudah digunakan,

ini dia contoh bagaimana Anda bisa membuat array numpy dan meneruskannya ke fungsi anggota kelas di 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])

Buffer.h

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

Anda juga dapat membuat modul Python dengan sangat mudah (dengan CMake), dengan cara ini Anda akan menghindari kompilasi ulang kode C ++ setiap saat.


2

pybind11 contoh runnable minimal

pybind11 sebelumnya disebutkan di https://stackoverflow.com/a/38542539/895245 tapi saya ingin memberikan contoh penggunaan konkret di sini dan beberapa diskusi lebih lanjut tentang implementasi.

Semua dan semua, saya sangat merekomendasikan pybind11 karena sangat mudah digunakan: Anda hanya menyertakan header dan kemudian pybind11 menggunakan templat ajaib untuk memeriksa kelas C ++ yang ingin Anda tampilkan ke Python dan melakukan itu secara transparan.

Kelemahan dari templat templat ini adalah memperlambat kompilasi dengan segera menambahkan beberapa detik ke file apa pun yang menggunakan pybind11, lihat misalnya penyelidikan yang dilakukan pada masalah ini . PyTorch setuju .

Berikut adalah contoh runnable minimal untuk memberi Anda perasaan betapa kerennya 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)

Kompilasi dan jalankan:

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

Contoh ini menunjukkan bagaimana pybind11 memungkinkan Anda dengan mudah mengekspos kelas ClassTestC ++ ke Python! Kompilasi menghasilkan file bernama class_test.cpython-36m-x86_64-linux-gnu.soyang class_test_main.pysecara otomatis mengambil sebagai titik definisi untukclass_test modul yang didefinisikan secara asli.

Mungkin realisasi betapa hebatnya ini hanya meresap jika Anda mencoba melakukan hal yang sama dengan tangan dengan Python API asli, lihat contoh ini, yang memiliki sekitar 10x lebih banyak kode: https://github.com /cirosantilli/python-cheat/blob/4f676f62e87810582ad53b2fb426b74eae52aad5/py_from_c/pure.c Pada contoh itu Anda dapat melihat bagaimana kode C harus dengan menyakitkan dan secara eksplisit mendefinisikan kelas Python sedikit demi sedikit dengan semua informasi yang dikandungnya (anggota, metode, metode lebih lanjut, metode metadata ...). Lihat juga:

pybind11 mengklaim serupa dengan Boost.Pythonyang disebutkan di https://stackoverflow.com/a/145436/895245 tetapi lebih minimal karena dibebaskan dari kegembiraan berada di dalam proyek Boost:

pybind11 adalah pustaka header-only ringan yang memperlihatkan tipe C ++ dalam Python dan sebaliknya, terutama untuk membuat binding Python dari kode C ++ yang ada. Tujuan dan sintaksnya mirip dengan pustaka Boost.Python yang sangat baik oleh David Abrahams: untuk meminimalkan kode boilerplate dalam modul ekstensi tradisional dengan menyimpulkan informasi jenis menggunakan intropeksi waktu kompilasi.

Masalah utama dengan Boost.Python — dan alasan untuk menciptakan proyek serupa — adalah Boost. Boost adalah rangkaian pustaka utilitas yang sangat besar dan kompleks yang bekerja dengan hampir setiap kompiler C ++ yang ada. Kompatibilitas ini memiliki biayanya: diperlukan trik trik dan solusi templat arcane untuk mendukung spesimen kompiler tertua dan paling bug. Sekarang karena kompiler yang kompatibel dengan C ++ 11 tersedia secara luas, alat berat ini telah menjadi ketergantungan yang terlalu besar dan tidak perlu.

Pikirkan perpustakaan ini sebagai Boost.Python versi mandiri yang kecil dengan segala sesuatu yang dilepaskan yang tidak relevan untuk pembuatan generasi. Tanpa komentar, file header inti hanya membutuhkan ~ 4K baris kode dan bergantung pada Python (2.7 atau 3.x, atau PyPy2.7> = 5.7) dan pustaka standar C ++. Implementasi yang ringkas ini dimungkinkan berkat beberapa fitur bahasa C ++ 11 yang baru (khususnya: tuple, fungsi lambda, dan templat variadic). Sejak dibuat, perpustakaan ini telah berkembang melampaui Boost.Python dalam banyak hal, yang mengarah ke kode pengikat yang secara dramatis lebih sederhana dalam banyak situasi umum.

pybind11 juga merupakan satu-satunya alternatif non-asli yang disorot oleh dokumentasi mengikat Microsoft Python C saat ini di: https://docs.microsoft.com/en-us/visualstudio/python/working-with-c-cpp-python-in- visual-studio? view = vs-2019 ( arsip ).

Diuji pada Ubuntu 18.04, pybind11 2.0.1, Python 3.6.8, GCC 7.4.0.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.