{"id":22279771,"url":"https://github.com/volpatto/simple_pybind_example","last_synced_at":"2025-07-28T18:31:47.439Z","repository":{"id":56345477,"uuid":"196642004","full_name":"volpatto/simple_pybind_example","owner":"volpatto","description":"A simple example of how to bind C++ code in Python","archived":false,"fork":false,"pushed_at":"2020-11-13T05:34:34.000Z","size":653,"stargazers_count":14,"open_issues_count":0,"forks_count":1,"subscribers_count":2,"default_branch":"master","last_synced_at":"2024-06-12T17:44:39.130Z","etag":null,"topics":["cmake","cpp","multilanguage","pybind","pybind11","python"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/volpatto.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2019-07-12T20:30:45.000Z","updated_at":"2023-11-18T09:34:21.000Z","dependencies_parsed_at":"2022-08-15T17:00:52.860Z","dependency_job_id":null,"html_url":"https://github.com/volpatto/simple_pybind_example","commit_stats":null,"previous_names":[],"tags_count":0,"template":true,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/volpatto%2Fsimple_pybind_example","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/volpatto%2Fsimple_pybind_example/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/volpatto%2Fsimple_pybind_example/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/volpatto%2Fsimple_pybind_example/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/volpatto","download_url":"https://codeload.github.com/volpatto/simple_pybind_example/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":227942901,"owners_count":17844868,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cmake","cpp","multilanguage","pybind","pybind11","python"],"created_at":"2024-12-03T15:21:01.724Z","updated_at":"2024-12-03T15:21:02.357Z","avatar_url":"https://github.com/volpatto.png","language":"Python","readme":"# Simple pybind example\n\n| Platform                               \t| Build status \t|\n|-----------------------------------------\t|--------------\t|\n| Ubuntu 18.04 LTS and Windows 2019       \t|  [![Build Status](https://dev.azure.com/volpatto/volpatto/_apis/build/status/volpatto.simple_pybind_example?branchName=master)](https://dev.azure.com/volpatto/volpatto/_build/latest?definitionId=3\u0026branchName=master)            \t|\n\n## TL;DR\n\nHere, a simple example about how to bind C++ code in Python is provided. The structure tries to be not invasive as much as possible concerning the C++ extension. \n\n## Now a longer description\n\nMy idea is to provide a structure to bind a C++ extension code to a Python base code. The C++ library (here, the extension we want to bind) can be anything that compiles standalone with its own `CMakeLists` (I use `CMake` here, so deal with it), and is exposed as a library that can be linked by others `CMakeLists`s.\nThe structural design aims to plug this extension in the Python base code by providing a binding interface using\n[pybind11](https://github.com/pybind/pybind11). Pursuing a generic purpose, I separate the binding module from the C++ extension code. Why? Well, my big and bold target here is to be not invasive while binding, so the binding duty is out of the\nC++ target library. Let's dive in to understand it better.\n\nThe basic tree structure of the package directory is shown below:\n\n```console\n├── CMakeLists.txt\n├── LICENSE\n├── python_package\n│   ├── bindings\n│   │   ├── bindings.cpp\n│   │   └── CMakeLists.txt\n│   ├── cpp_binding\n│   │   └── example_binding.cpython-37m-x86_64-linux-gnu.so\n│   ├── _cpp_package\n│   │   ├── CMakeLists.txt\n│   │   ├── example_cpp.cpp\n│   │   └── example_cpp.hpp\n│   ├── foo_module.py\n│   └── __init__.py\n├── README.md\n├── setup.cfg\n├── setup.py\n└── tests\n    └── test_foo.py\n```\n\nA generic python package named (guess what?! wait for it) `python_package` is our Python module. Inside it, \nall the Python lib stuff is located. Here, just for simplifying things, we consider that there is only one Python module (`foo_module.py`). \nNow, beside Python modules, I inserted the C++ extension. Just as a note, it could be placed out of `python_package` dir, say, `external` or `lib` dirs, for example. Since it's only an extension, not a huge C++ lib actually, I do prefer to put it beside Python modules (personal tastes, you know). The C++ extension is in `_cpp_package` dir. The binding interface is\nplaced in `binding` dir, with a proper `binding.cpp` file which does all the witchcraft with `pybing11`. An important point\nhere is to take a look in the `CMakeLists.txt` (actually all the `CMakeLists.txt` worth it, do not underestimate `CMake`'s\nevil power) to get a glance of how to use pybind on a target link library.\n\nAfter all the compilation and linking processes, a shared library will be generated in `cpp_binding` dir.\nIt can be imported from a python script from this point. But how we could pack it in a Python package? Well, the `setup.py` will do the \ntrick for you. You could install it with:\n\n```console\npython setup.py develop\n```\n\nor\n\n```console\npython setup.py install\n```\n\nor even with the beloved `pip`:\n\n```console\npip install -e ./\n```\n\nEverything above will install the Python package with the C++ extension for you (in a development mode, btw, but working). The\n`setup.py` is heavily based on the [official pybind11 cmake example](https://github.com/pybind/cmake_example) and\nin this [helpful post here](https://www.benjack.io/2018/02/02/python-cpp-revisited.html). To be honest, \nI must say that these two sources inspired me also in several others features I aimed to reach here. So kudos to the authors!\n\n## Tests\n\nWith everything working properly, here come the goodies: Testing C++ codes with Python with the delightful `pytest`.\n\n\u003e \"- Oh! Do you mean that there is no `Boost.Test` or `Catch2`?! Wtf, man?! They are great!\"\n\nYeah, I agree. But Python can make things faster (polemical pause, awkward silence). Watch out, I didn't say what will get faster!\nIn my humble and pretty insignificant opinion, testing things with `pytest` is easier than testing in C++. It could turn the\ntesting creation stage quickier (of course, if you have good and well designed bindings available).\n\nExamples of tests are provided in `tests` dir. The tests are performed using `pytest`, but could be any other Python test lib.\n\nIf you want to see tests working, I defined an alias for it in `setup.cfg` file, just run the below command in your \nterminal:\n\n```console\npython setup.py test\n```\n\n## Requirements\n\nI create isolated environments with [conda](https://conda.io/en/latest/). You can use and create an environment with all the\nrequirement just doing the following in the repo root:\n\n```console\nconda env create -f environment.yml\n```\n\nThis will create an environment named `cpp-bindings`. Activate it and you will got all that you need.\n\n\u003e \"- Oh! I don't use conda! I even don't know how to use it. Wait, I even don't know what is conda! What could I do?\"\n\nWell, no problem. Be sure that you have the following things properly installed in your system (or anything you prefer rather than `conda env`s):\n\n* clangdev \u003e=6.0 (I use `clang` compiler here, but things *should* work OK with `g++` as well)\n* cmake\n* make\n* pybind11 (this one is the most important! you have to be able to find it with CMake's `find_package` command)\n* pytest (to run the tests)\n* pytest-runner\n* python \u003e=3.6.7 (Python greater than 3.7 would be nice!)\n\nYou could use Python `virtualenv`s as well, I think it wouldn't be a problem (but I won't do it, if you do you tell me).\n\n## Contributing\n\n\u003e \"- Oh! I think you did a terrible work here. This repo is a piece of LOVE!\" (edited due to educational reasons)\n\nThank you! You are very nice! I think you are also a great programmer, probably far better than me (I try my best, I \nswear). If you have any suggestion, correction, improvements or anything that could increase the quality of the content\nof the present repo, please feel free to open an issue or, even better, send a PR. I will **really** appreciate that!\n\n## Usage\n\n\u003e \"- Oh! I think this repo is a good starting point for a project I have in mind! Can I use it?!\"\n\nDon't say more. Free software, MIT license. If it help you in any way, I will be very happy! At least I helped someone! This way I am contributing to a better world.\n\n## Contact\n\nMy name is Diego Volpatto, feel free to contact me through the email dtvolpatto@gmail.com. However, there is no guarantee\nthat I can help you.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvolpatto%2Fsimple_pybind_example","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fvolpatto%2Fsimple_pybind_example","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvolpatto%2Fsimple_pybind_example/lists"}