diff --git a/.github/ISSUE_TEMPLATE/problem-report.md b/.github/ISSUE_TEMPLATE/problem-report.md new file mode 100644 index 0000000..c2b8e7e --- /dev/null +++ b/.github/ISSUE_TEMPLATE/problem-report.md @@ -0,0 +1,29 @@ +--- +name: Problem report +about: Create a problem report to help us help you +title: '' +labels: '' +assignees: '' + +--- + +**Describe the bug** +A clear and concise description of what the bug is. + +**Error message(s)** + +**Environment:** + - OS: [e.g. Ubuntu Linux, openSUSE Linux, OSX, Windows] + - Version [e.g. 22] + - Python Version + - Source of Python [e.g., self-compiled, OS version, ...] + - Boost Version + - Source of Boost [e.g., self-compiled, OS version, ...] + - Compiler Version + +**Log of compilation** + + + +**Additional context** +Add any other context about the problem here. diff --git a/.github/dco.yml b/.github/dco.yml new file mode 100644 index 0000000..4ac50ad --- /dev/null +++ b/.github/dco.yml @@ -0,0 +1,3 @@ +require: + members: false + diff --git a/.gitignore b/.gitignore index 9132d95..e1fa31f 100644 Binary files a/.gitignore and b/.gitignore differ diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..1dc9750 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,20 @@ +language: cpp +script: ./build.sh + +matrix: + include: + - os: linux + addons: + apt: + sources: + - ubuntu-toolchain-r-test + packages: + - libboost-all-dev + + - os: osx + osx_image: xcode9.2 + env: + - PYTHON_EXECUTABLE: /usr/local/bin/python + before_install: + - brew update && brew bundle + - brew unlink python && brew install python@2 diff --git a/01-HelloWorld/CMakeLists.txt b/01-HelloWorld/CMakeLists.txt index 1f4d2f8..66af19c 100644 --- a/01-HelloWorld/CMakeLists.txt +++ b/01-HelloWorld/CMakeLists.txt @@ -1,4 +1,4 @@ PYTHON_ADD_MODULE(hello hello.cpp) FILE(COPY hello.py DESTINATION .) -ADD_TEST(01-HelloWorld hello.py) +ADD_TEST(NAME 01-HelloWorld COMMAND ${PYTHON_EXECUTABLE} hello.py) diff --git a/02-ExposingClasses/CMakeLists.txt b/02-ExposingClasses/CMakeLists.txt index 9b7b59e..5e7f969 100644 --- a/02-ExposingClasses/CMakeLists.txt +++ b/02-ExposingClasses/CMakeLists.txt @@ -1,4 +1,4 @@ PYTHON_ADD_MODULE(classes classes.cpp) FILE(COPY classes.py DESTINATION .) -ADD_TEST(02-ExposingClasses classes.py) +ADD_TEST(NAME 02-ExposingClasses COMMAND ${PYTHON_EXECUTABLE} classes.py) diff --git a/02-ExposingClasses/classes.cpp b/02-ExposingClasses/classes.cpp index 88a75a9..dfcdcc6 100644 --- a/02-ExposingClasses/classes.cpp +++ b/02-ExposingClasses/classes.cpp @@ -1,10 +1,24 @@ #include +#include +#include #include +#include +#include struct World { void set(std::string msg) { mMsg = msg; } + void many(boost::python::list msgs) { + long l = len(msgs); + std::stringstream ss; + for (long i = 0; i0) ss << ", "; + std::string s = boost::python::extract(msgs[i]); + ss << s; + } + mMsg = ss.str(); + } std::string greet() { return mMsg; } std::string mMsg; }; @@ -16,5 +30,6 @@ BOOST_PYTHON_MODULE(classes) class_("World") .def("greet", &World::greet) .def("set", &World::set) + .def("many", &World::many) ; }; diff --git a/02-ExposingClasses/classes.py b/02-ExposingClasses/classes.py index cdbc2a8..0032809 100755 --- a/02-ExposingClasses/classes.py +++ b/02-ExposingClasses/classes.py @@ -6,4 +6,7 @@ t.set("bom dia!") print (t.greet()) +t.many(['Good Morning', 'Buon giorno', 'Kali mera']) +print (t.greet()) + diff --git a/03-Constructors/CMakeLists.txt b/03-Constructors/CMakeLists.txt index f33b5db..9e145bf 100644 --- a/03-Constructors/CMakeLists.txt +++ b/03-Constructors/CMakeLists.txt @@ -1,4 +1,4 @@ PYTHON_ADD_MODULE(ctor ctor.cpp) FILE(COPY ctor.py DESTINATION .) -ADD_TEST(03-Constructors ctor.py) +ADD_TEST(NAME 03-Constructors COMMAND ${PYTHON_EXECUTABLE} ctor.py) diff --git a/04-ClassMembers/CMakeLists.txt b/04-ClassMembers/CMakeLists.txt index 50f3f0b..d0912ff 100644 --- a/04-ClassMembers/CMakeLists.txt +++ b/04-ClassMembers/CMakeLists.txt @@ -1,5 +1,5 @@ PYTHON_ADD_MODULE(member member.cpp) FILE(COPY member.py DESTINATION .) -ADD_TEST(04-ClassMembers member.py) +ADD_TEST(NAME 04-ClassMembers COMMAND ${PYTHON_EXECUTABLE} member.py) diff --git a/05-Inheritance/CMakeLists.txt b/05-Inheritance/CMakeLists.txt index 41fb1f1..02748ee 100644 --- a/05-Inheritance/CMakeLists.txt +++ b/05-Inheritance/CMakeLists.txt @@ -1,5 +1,5 @@ PYTHON_ADD_MODULE(inheritance inheritance.cpp) FILE(COPY inheritance.py DESTINATION .) -ADD_TEST(05-Inheritance inheritance.py) +ADD_TEST(NAME 05-Inheritance COMMAND ${PYTHON_EXECUTABLE} inheritance.py) diff --git a/06-VirtualFunctionsInPython/CMakeLists.txt b/06-VirtualFunctionsInPython/CMakeLists.txt index b3548da..fe21fb9 100644 --- a/06-VirtualFunctionsInPython/CMakeLists.txt +++ b/06-VirtualFunctionsInPython/CMakeLists.txt @@ -1,5 +1,5 @@ PYTHON_ADD_MODULE(virtual virtual.cpp) FILE(COPY virtual.py DESTINATION .) -ADD_TEST(06-VirtualFunctionsInPython virtual.py) +ADD_TEST(NAME 06-VirtualFunctionsInPython COMMAND ${PYTHON_EXECUTABLE} virtual.py) diff --git a/07-Operators/CMakeLists.txt b/07-Operators/CMakeLists.txt index 5a6b207..41226c4 100644 --- a/07-Operators/CMakeLists.txt +++ b/07-Operators/CMakeLists.txt @@ -1,5 +1,5 @@ PYTHON_ADD_MODULE(operators operators.cpp) FILE(COPY operators.py DESTINATION .) -ADD_TEST(07-Operators operators.py) +ADD_TEST(NAME 07-Operators COMMAND ${PYTHON_EXECUTABLE} operators.py) diff --git a/08-CallPolicies/CMakeLists.txt b/08-CallPolicies/CMakeLists.txt index 0799ed9..fddcbf1 100644 --- a/08-CallPolicies/CMakeLists.txt +++ b/08-CallPolicies/CMakeLists.txt @@ -1,5 +1,5 @@ PYTHON_ADD_MODULE(policies policies.cpp) FILE(COPY policies.py DESTINATION .) -ADD_TEST(08-CallPolicies policies.py) +ADD_TEST(NAME 08-CallPolicies COMMAND ${PYTHON_EXECUTABLE} policies.py) diff --git a/09-Overloading/CMakeLists.txt b/09-Overloading/CMakeLists.txt index bf82d4a..988e823 100644 --- a/09-Overloading/CMakeLists.txt +++ b/09-Overloading/CMakeLists.txt @@ -1,5 +1,5 @@ PYTHON_ADD_MODULE(overload overload.cpp) FILE(COPY overload.py DESTINATION .) -ADD_TEST(09-Overloading overload.py) +ADD_TEST(NAME 09-Overloading COMMAND ${PYTHON_EXECUTABLE} overload.py) diff --git a/10-Embedding/CMakeLists.txt b/10-Embedding/CMakeLists.txt index 0aeda1f..3fac1d9 100644 --- a/10-Embedding/CMakeLists.txt +++ b/10-Embedding/CMakeLists.txt @@ -3,5 +3,5 @@ PYTHON_ADD_MODULE(mymodule mymodule.cpp) ADD_EXECUTABLE(embedding mymodule.cpp embedding.cpp) TARGET_LINK_LIBRARIES(embedding ${Boost_LIBRARIES} ${PYTHON_LIBRARIES}) FILE(COPY embedding.py DESTINATION .) -ADD_TEST(10-Embedding embedding) +ADD_TEST(NAME 10-Embedding COMMAND embedding) diff --git a/11-Iterators/CMakeLists.txt b/11-Iterators/CMakeLists.txt index c8f4aaf..5a828c4 100644 --- a/11-Iterators/CMakeLists.txt +++ b/11-Iterators/CMakeLists.txt @@ -1,5 +1,5 @@ PYTHON_ADD_MODULE(iterators iterators.cpp) FILE(COPY iterators.py DESTINATION .) -ADD_TEST(11-Iterators iterators.py) +ADD_TEST(NAME 11-Iterators COMMAND ${PYTHON_EXECUTABLE} iterators.py) diff --git a/12-Exceptions/CMakeLists.txt b/12-Exceptions/CMakeLists.txt index 277ae3a..c97a750 100644 --- a/12-Exceptions/CMakeLists.txt +++ b/12-Exceptions/CMakeLists.txt @@ -1,5 +1,5 @@ PYTHON_ADD_MODULE(myexceptions myexceptions.cpp) FILE(COPY myexceptions.py DESTINATION .) -ADD_TEST(12-Exceptions myexceptions.py) +ADD_TEST(NAME 12-Exceptions COMMAND ${PYTHON_EXECUTABLE} myexceptions.py) diff --git a/12-Exceptions/myexceptions.cpp b/12-Exceptions/myexceptions.cpp index 4dc272f..fb79ad8 100644 --- a/12-Exceptions/myexceptions.cpp +++ b/12-Exceptions/myexceptions.cpp @@ -17,5 +17,5 @@ BOOST_PYTHON_MODULE(myexceptions) { register_exception_translator(translateException); - def("someFunction", someFunction); + def("someFunction", &someFunction); } diff --git a/13-AutoInstantiation/CMakeLists.txt b/13-AutoInstantiation/CMakeLists.txt index 2e39c99..d601eb1 100644 --- a/13-AutoInstantiation/CMakeLists.txt +++ b/13-AutoInstantiation/CMakeLists.txt @@ -3,5 +3,5 @@ ADD_EXECUTABLE(auto_instance myextension.cpp auto_instance.cpp) TARGET_LINK_LIBRARIES(auto_instance ${Boost_LIBRARIES} ${PYTHON_LIBRARIES}) FILE(COPY auto_instance.py DESTINATION .) SET( ENV{PYTHONPATH} . ) -ADD_TEST(13-AutoInstantiation auto_instance) +ADD_TEST(NAME 13-AutoInstantiation COMMAND auto_instance) diff --git a/Brewfile b/Brewfile new file mode 100644 index 0000000..625a1df --- /dev/null +++ b/Brewfile @@ -0,0 +1,3 @@ +brew 'boost-python' + + diff --git a/CMakeLists.txt b/CMakeLists.txt index aafc6ea..95c9813 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,12 +1,38 @@ cmake_minimum_required(VERSION 2.8.3) + FIND_PACKAGE(PythonInterp) -FIND_PACKAGE(PythonLibs) -if(APPLE AND ${PYTHON_VERSION_MAJOR} EQUAL 3) - FIND_PACKAGE(Boost COMPONENTS python3) + +if (PYTHONINTERP_FOUND) + if (UNIX AND NOT APPLE) + if (PYTHON_VERSION_MAJOR EQUAL 3) + FIND_PACKAGE(Boost COMPONENTS python${PYTHON_VERSION_SUFFIX}) + FIND_PACKAGE(PythonInterp 3) + FIND_PACKAGE(PythonLibs 3 REQUIRED) + else() + FIND_PACKAGE(Boost COMPONENTS python) + FIND_PACKAGE(PythonInterp) + FIND_PACKAGE(PythonLibs REQUIRED) + endif() + else() + if (PYTHON_VERSION_MAJOR EQUAL 3) + FIND_PACKAGE(Boost COMPONENTS python${PYTHON_VERSION_MAJOR}${PYTHON_VERSION_MINOR}) + FIND_PACKAGE(PythonInterp 3) + FIND_PACKAGE(PythonLibs 3 REQUIRED) + else() + FIND_PACKAGE(Boost COMPONENTS python${PYTHON_VERSION_MAJOR}${PYTHON_VERSION_MINOR}) + FIND_PACKAGE(PythonInterp) + FIND_PACKAGE(PythonLibs REQUIRED) + endif() + endif() else() - FIND_PACKAGE(Boost COMPONENTS python) + message("Python not found") endif() +message(STATUS "PYTHON_LIBRARIES = ${PYTHON_LIBRARIES}") +message(STATUS "PYTHON_EXECUTABLE = ${PYTHON_EXECUTABLE}") +message(STATUS "PYTHON_INCLUDE_DIRS = ${PYTHON_INCLUDE_DIRS}") +message(STATUS "Boost_LIBRARIES = ${Boost_LIBRARIES}") + ENABLE_TESTING() INCLUDE_DIRECTORIES(${Boost_INCLUDE_DIRS} ${PYTHON_INCLUDE_DIRS}) LINK_LIBRARIES(${Boost_LIBRARIES} ${PYTHON_LIBRARIES}) # Deprecated but so convenient! diff --git a/DCO.md b/DCO.md new file mode 100644 index 0000000..f34d70b --- /dev/null +++ b/DCO.md @@ -0,0 +1,43 @@ +## Sign your work - the Developer's Certificate of Origin +The sign-off is a simple line at the end of the explanation for the patch, which certifies that you wrote it or otherwise have the right to pass it on as an open-source patch. The rules are pretty simple: if you can certify the below (from [developercertificate.org](https://www.developercertificate.org)): + +> Developer's Certificate of Origin 1.1 +> +> By making a contribution to this project, I certify that: +> +> (a) The contribution was created in whole or in part by me and I +> have the right to submit it under the open source license +> indicated in the file; or +> +> (b) The contribution is based upon previous work that, to the best +> of my knowledge, is covered under an appropriate open source +> license and I have the right under that license to submit that +> work with modifications, whether created in whole or in part +> by me, under the same open source license (unless I am +> permitted to submit under a different license), as indicated +> in the file; or +> +> (c) The contribution was provided directly to me by some other +> person who certified (a), (b) or (c) and I have not modified +> it. +> +> (d) I understand and agree that this project and the contribution +> are public and that a record of the contribution (including all +> personal information I submit with it, including my sign-off) is +> maintained indefinitely and may be redistributed consistent with +> this project or the open source license(s) involved. + +#### DCO Sign-Off Methods + +The DCO requires a sign-off message in the following format appear on each commit in the pull request: + +> Signed-off-by: Random J Developer + +using your real name (sorry, no pseudonyms or anonymous contributions.) + +The DCO text can either be manually added to your commit body, or you can add either **`-s`** or **`--signoff`** to your usual git commit commands. If you forget to add the sign-off you can also amend a previous commit with the sign-off by running **`git commit --amend -s`**. If you've pushed your changes to Github already you'll need to force push your branch after this with ***`git push -f`**. + + +#### Alternative Sign-Off Methods in rare cases + +If it is really no option for you to disclose your real name and email address, there might be a chance that you can get your contribution accepted. In this case please contact the maintainers directly and verify the adherence to the DCO of the contribution manually. This might include quite some legal overhead for both parties. diff --git a/Dockerfile.ubuntu b/Dockerfile.ubuntu new file mode 100644 index 0000000..47dad3f --- /dev/null +++ b/Dockerfile.ubuntu @@ -0,0 +1,11 @@ +FROM ubuntu:bionic +RUN apt-get update && apt-get install -y libboost-all-dev python-dev git cmake g++ gdb python-dbg +RUN mkdir /work +VOLUME /work/src +WORKDIR /work +RUN git clone https://github.com/TNG/boost-python-examples.git src && ./build.sh || true +# +# alternatively to the last RUN, one can share the source with the host system: +# docker build -t bp:latest . +# docker run -t -i -v $PWD:/work/src bp:latest +# mkdir build && cd build && cmake ../src && make && make test diff --git a/README.md b/README.md index 171c97b..e3ac2f3 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,8 @@ - # boost::python examples +[![Build Status](https://travis-ci.org/TNG/boost-python-examples.svg?branch=master)](https://travis-ci.org/TNG/boost-python-examples) +[![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2FTNG%2Fboost-python-examples.svg?type=shield)](https://app.fossa.io/projects/git%2Bgithub.com%2FTNG%2Fboost-python-examples?ref=badge_shield) + These are a few examples on how to use the boost::python library to extend Python with C++ libraries. Some of the are based on the [existing tutorial for boost::python from Joel de Guzman](http://www.boost.org/doc/libs/1_46_1/libs/python/doc/tutorial/doc/html/index.html "Boost.Python tutorial"). Others are independent. @@ -9,11 +11,11 @@ Others are independent. ### general + [CMake](http://www.cmake.org "CMake project page") (>= 2.8.3) -+ [Boost](http://www.boost.org/ "Boost project page") (tested with 1.4.2, but should work with >= 1.3.2) -+ [Python](http://www.python.org "Python home page") (tested with 2.7, but should work with >= 2.2) ++ [Boost](http://www.boost.org/ "Boost project page") (tested with 1.67, but should work with >= 1.3.2) ++ [Python](http://www.python.org "Python home page") (tested with 2.7 and 3.6, but should work with >= 2.2) + a C++ compiler for your platform, e.g. [GCC](http://gcc.gnu.org "GCC home") or [MinGW](http://www.mingw.org "Minimalist GNU for Windows") -The examples should work on Linux, Windows and Mac, but currently have not been tested under Windows. +The examples should work on Linux, Windows and OSX, but currently [have not been tested much under Windows](https://github.com/TNG/boost-python-examples/issues/10#issuecomment-326828479). ### Mac OS X with [homebrew](http://brew.sh) @@ -45,16 +47,53 @@ The code works with Python 3 both on Linux and on OS X. However, there are sever + Build Boost::Python against Python 3 (needs at least version 1.56.0) + make sure `python` resolves to python3 (e.g., by using a python3 VE) -+ run `cmake -DBOOST_ROOT=xxx ..` ++ run `./build.sh` ### OS X (again with homebrew) Some effort has been made to make Python 3 compilation automatic, by making modifications to `build.sh` and `CMakeLists.txt` that account for quirks on the Apple platform regarding cmake, paths, and naming conventions for python/python3. Having said that, if you use `build.sh`, then you will still need to do the following: -+ Build Boost::Python against Python 3 (needs at least version 1.56.0) ++ Build Boost::Python against Python 3 (needs at least version 1.56.0) or `brew install boost-python3` + make sure `python` resolves to python3 (e.g., by using virtualenv) ++ check that `cmake` uses matching python interpreter and libraries (down to the last digit). Otherwise you run into [#17](https://github.com/TNG/boost-python-examples/issues/17). If you are building without `build.sh`, then you will additionally need to: -+ run `cmake -DBOOST_ROOT=xxx -DPYTHON_LIBRARY=xxx -DPYTHON_INCLUDE_DIR=xxx ..` -+ As of the time of this writing, the naming convention is that python2 is called "python" and python3 is called "python3" on the Apple platform. Therefore, in `CMakeLists.txt` verify that the line `FIND_PACKAGE(Boost COMPONENTS python)` is changed to `FIND_PACKAGE(Boost COMPONENTS python3)`. ++ run `cmake -DBOOST_LIBRARYDIR=xxx -DPYTHON_LIBRARY=xxx -DPYTHON_INCLUDE_DIR=xxx ..` + +## Contributing + +Contributions are very welcome. The following will provide some helpful guidelines. + +### How to contribute + +If you want to submit a contribution, please follow the following workflow: + +* Fork the project +* Create a feature branch +* Add your contribution +* When you're completely done, build the project and run all tests +* Create a Pull Request + +### Commits + +Commit messages should be clear and fully elaborate the context and the reason of a change. +If your commit refers to an issue, please post-fix it with the issue number, e.g. + +``` +Issue: #123 +``` + +Furthermore, commits should be signed (`git commit -s`) according to the [DCO](DCO.md). + +### Pull Requests + +If your Pull Request resolves an issue, please add a respective line to the end, like + +``` +Resolves #123 +``` + + +## License +[![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2FTNG%2Fboost-python-examples.svg?type=large)](https://app.fossa.io/projects/git%2Bgithub.com%2FTNG%2Fboost-python-examples?ref=badge_large) \ No newline at end of file diff --git a/build.sh b/build.sh index 2bda7f6..802f3c8 100755 --- a/build.sh +++ b/build.sh @@ -6,8 +6,8 @@ cd ${0%%$(basename $0)} mkdir build cd build -if [[ "$OSTYPE" == "linux-gnu" ]]; then - cmake -DCMAKE_BUILD_TYPE=DEBUG .. && make && make test +if [[ "$OSTYPE" == "linux-gnu" || "$OSTYPE" == "linux" ]]; then + cmake -DPYTHON_VERSION_SUFFIX=-py3 -DCMAKE_BUILD_TYPE=DEBUG .. && make && make test elif [[ "$OSTYPE" == "darwin"* ]]; then PYTHON_VERSION=`python -c "import sys;t='{v[0]}.{v[1]}'.format(v=list(sys.version_info[:2]));sys.stdout.write(t)";` PYTHON_LIBRARY=/usr/local/Frameworks/Python.framework/Versions/$PYTHON_VERSION/lib/libpython$PYTHON_VERSION.dylib