O poder do Pybind11 é capturado pela seguinte citação do ReadMe do Pybind11:
O PYBIND11 é uma biblioteca apenas de cabeçalho leve que expõe os tipos de C ++ em Python e vice-versa, principalmente para criar ligações Python do código C ++ existente. Seus objetivos e sintaxe são semelhantes ao excelente Boost.python Library por David Abrahams ...
O principal problema com o boost.python - e o motivo da criação de um projeto tão semelhante - é o Boost. O Boost é um conjunto de bibliotecas de serviços públicos extremamente grande e complexo que trabalha com quase todos os compiladores C ++ existentes. ... Agora que os compiladores compatíveis com 11 compatíveis com C ++ estão amplamente disponíveis, esse mecanismo pesado se tornou uma dependência excessivamente grande e desnecessária.
Este repositório contém vários exemplos para o uso do PYBIND11. Embora a documentação on -line fornecida pelos desenvolvedores do PYBIND11 torne o uso relativamente simples, vários exemplos - como fornecidos aqui - tornam o PYBIND11 ainda mais fácil de usar. Esses exemplos são destinados a você começar mais rápido com o PYBIND11. No entanto, eles não são exaustivos e nem sempre fornecem a escolha ideal. Portanto, é altamente aconselhável pensar por si mesmo . Além disso, contribuições com exemplos simples semelhantes (ou melhorando ainda mais os exemplos existentes) são altamente bem -vindos . Por favor, registre uma solicitação de tração ou um problema no Github ou entre em contato comigo.
Para dar crédito onde o crédito é devido:
Os criadores do Pybind11 fizeram um ótimo trabalho! É realmente fácil de usar e muito leve. Além disso, a documentação já está bastante completa.
Os exemplos disponibilizados por Cliburn Chan e Janice McCarthy, na Duke University, foram de enorme ajuda. Por favor, leia também a documentação deles.
Observe que também existem casos de teste que dobram como exemplos no repositório Pybind11, mas estes não são muito perspicazes quando você é novo no PYBIND11.
Finalmente, o PYBIND11 é usado ativamente. Portanto, pode -se procurar bibliotecas mantidas ativamente para soluções específicas. Por exemplo:
O módulo PYBIND11 (que é apenas o cabeçalho!) É incluído como um submódulo deste repositório. Isso requer alguma atenção ao clonar este projeto. Existem duas opções:
A opção mais simples é:
git clone --recursive https://github.com/tdegeus/pybind11_examples.gitIsso baixará o submódulo até a versão usada neste projeto. Para atualizar para a última confirmação do próprio submódulo:
git submodule update --remoteTambém é possível fazer o download diretamente do submódulo da fonte:
git clone https://github.com/tdegeus/pybind11_examples.git
cd pybind11_examples
git submodule init
git submodule updateA Biblioteca Eigen é usada em alguns dos exemplos numpy. A partir desses exemplos, pode -se observar que, através de Pybind11, Eigen e Numpy são realmente módulos de aperto de mão. Quase nenhum código é necessário para criar a interface C ++/Python. Observe que a maior parte da simplicidade depende da passagem de cópias, é necessária alguma atenção se alguém quiser passar apenas por referência.
Eigen não precisa de instalação porque também é apenas o cabeçalho. Só é preciso baixar os arquivos e incluir os cabeçalhos na hora da compilação.
Em geral, pode -se baixar e instalar Eigen por:
mkdir /path/to/temp/build
cmake /path/to/eigen/download
make installPara o macOS, pode -se simplesmente usar
brew install eigen
Depois disso, compilar com
clang++ -I/path/to/eigen/instalation ...Observe que, quando configurado corretamente (que normalmente é o caso), o pkg-config pode ser usado para acompanhar os caminhos:
clang++ ` pkg-config --cflags eigen3 ` ...Ou pode -se usar cmake (veja abaixo).
Se você tem uma biblioteca simples, pode querer fazer tudo sozinho. Nesse caso, você compila sua fonte C ++ a um objeto compartilhado vinculado ao Python. Isso se resume a
c++ -O3 -shared -std=gnu++11 -I ./pybind11/include ` python3-config --cflags --ldflags --libs ` example.cpp -o example.so -fPIC Os aplicativos PYBIND11 podem ser compilados com muita facilidade usando CMake. Para a simplicidade, o Pybind11 é incluído como um sub-fold dos exemplos abaixo (de fato, usando um link simbólico para muitas cópias), para que possamos usar um CMakeLists.txt como:
cmake_minimum_required ( VERSION 2.8.12)
project (example)
add_subdirectory (pybind11)
pybind11_add_module(example example.cpp) (pelo qual este módulo de exemplo consiste em um único arquivo de origem example.cpp ). Para compilá -lo, use:
cd /path/to/build
cmake /path/to/example/src
make Quando Eigen é 'instalado', ele pode ser facilmente incluído adicionando o seguinte em CMakeLists.txt :
find_package ( PkgConfig )
pkg_check_modules( EIGEN3 REQUIRED eigen3 )
include_directories ( ${EIGEN3_INCLUDE_DIRS} ) O padrão C ++ 14 pode ser usado incluindo o seguinte em CMakeLists.txt :
set (CMAKE_CXX_STANDARD 14) Um arquivo setup.py pode ser adicionado à sua biblioteca. Você pode então compilar e instalar usando
python3 setup.py build
python3 setup.py install Embora escrever o setup.py não seja difícil, não está coberto aqui. Pode -se usar algumas ferramentas incluídas no CPPMAT, que podem ser instaladas com PIP (por exemplo, pip3 install cppmat ). Além disso, pode olhar para o setup.py , por exemplo, GoosEtensor ou vários outros dos meus repositórios.
Este exemplo apresenta uma função modify que pega uma lista (somente leitura), multiplica todas as entradas por duas e a devolve como uma lista de duplas (consulte example.cpp ). Do python, essa função está contida em um example simples de módulo (consulte test.py ).
O objetivo deste exemplo é mostrar como fazer uma função aceitar uma lista, como convertê -la para o std::vector C ++ padrão e como retornar um novo std::vector (ou List). Observe que a operação real não é muito importante, é a interface ilustrada.
Para compilar, empregue cmake, pelo qual as instruções de compilação são lidas em CMakeLists.txt por posteriormente:
cmake .
makeOu compilar diretamente usando:
c++ -O3 -shared -std=gnu++11 -I ./pybind11/include ` python3-config --cflags --ldflags --libs ` example.cpp -o example.so -fPICExecute o exemplo por:
python3 test.pyPara executar com o Python 2, basta substituir as duas ocorrências de "Python3" acima por "Python". Para modificar as instruções do CMake, encontre mais online.
O mesmo que o exemplo anterior, mas com uma lista aninhada.
Uma função modify que converte as entradas de uma matriz unidimensional em números inteiros e, em seguida, multiplica essas entradas por 10.
O objetivo deste exemplo é mostrar como fazer uma função aceitar uma matriz Numpy unidimensional, como convertê-lo para o std::vector e como retornar uma matriz Numpy unidimensional. Observe que a interface gerada usando o PYBind11 é tão flexível que aceita entradas de lista no lado do Python.
Um length de função. Esta função aceita uma 'matriz' na qual compreende uma lista de vetores de posição 2D, como linhas. O resultado é novamente uma 'matriz' com para cada linha a posição "X" e "Y" e o comprimento do vetor de posição 2-D.
Duas funções det e inv que usam a biblioteca Eigen.
O objetivo deste exemplo é mostrar o quão trivial é a interação entre C ++/Eigen e Python/Numpy.
Para compilar usando o cmake e para executar, siga as instruções acima (pelas quais os cabeçalhos do eigen estão incluídos no CMakeLists.txt . Para compilar diretamente, além dos cabeçalhos do eigen devem ser incluídos:
c++ -O3 -shared -std=gnu++11 -I /path/to/eigen -I ./pybind11/include ` python3-config --cflags --ldflags --libs ` example.cpp -o example.so -fPICPor exemplo, no macOS com homebrew:
c++ -O3 -shared -std=gnu++11 -I /usr/local/Cellar/eigen/3.3.1/include/eigen3 -I ./pybind11/include ` python3-config --cflags --ldflags --libs ` example.cpp -o example.so -fPIC Uma classe CustomVectorXd personalizada com uma função mul . Esta classe usa a biblioteca Eigen. Também inclui um argumento padrão.
Além disso, este exemplo possui uma função trans (totalmente não relacionada à classe CustomVectorXd Custom). O objetivo é mostrar como devolver um novo Eigen::VectorXi (ou Numpy-Array).
Uma função sobrecarregada mul . Esta função age 'de maneira diferente' se for chamada com argumentos int ou argumentos double . Observe que o comportamento padrão do PYBind11 é bastante robusto. Ao chamar a função com um int e um argumento double , o módulo escolherá a versão double do mul (e lançará o argumento int em um double ).
Para compilar, verifique se o padrão C ++ 14 é usado, por exemplo, incluindo -std=c++14 como argumento do compilador.
Semelhante ao exemplo anterior, mas com argumentos de Eigen (ou seja, argumentos numpy do lado do Python).
Para compilar, verifique se o padrão C ++ 14 é usado.
Este exemplo inclui uma classe de matriz personalizada em C ++ (em matrix.h ). Esta classe é acoplada a uma matriz numpy usando uma interface simples (em pybind_matrix.h ). Consequentemente, as funções (no example.cpp ) não precisam de nenhum código de invólucro especial.
Veja também esta discussão sobre o transbordamento da pilha.
Este exemplo apresenta uma maneira de interagir com um enumerador no C ++. Em princípio, a interface é direta, mas merece um 'truque'. Aqui, um submódulo é usado para poder interagir com o enumerador da mesma maneira que em C ++.
Este exemplo contém um exemplo clássico em que uma ou mais classes são derivadas de um determinado pai ou modelo. Este exemplo em particular contém dois animais, um Dog e um Cat , que são derivados de uma classe Animal genéricos. Há uma talk de função que aceita o Animal genérico e, portanto, qualquer uma das classes derivadas.
Este caso em particular requer uma interface mais envolvida, como é descrito na documentação.
Este exemplo apresenta um CRTP simples com a classe 'Base' e e uma 'derivada' e seu registro na API PYBIND11 .
Às vezes, py::overload_cast não consegue resolver sua função, por exemplo, quando o tipo de retorno não pode ser inferido. Nesse caso, você pode ser explícito por static_cast ing um ponteiro para sua função, mais informações podem ser encontradas na documentação.