diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index aa0b6cb84d2e1b5665ae1d4a1f5d6326f817d88b..dcb58f13a83f9b01578123fb3fdd3640ef3d229c 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,37 +1,39 @@ Python 2.7: script: - py_version=2.7 - - EXTRA_INSTALL=numpy + - EXTRA_INSTALL="numpy pybind11" - curl -L -O -k https://gitlab.tiker.net/inducer/ci-support/raw/master/build-and-test-py-project.sh - ". ./build-and-test-py-project.sh" tags: - python2.7 except: - tags + Python 3.5: script: - py_version=3.5 - - EXTRA_INSTALL=numpy + - EXTRA_INSTALL="numpy pybind11" - curl -L -O -k https://gitlab.tiker.net/inducer/ci-support/raw/master/build-and-test-py-project.sh - ". ./build-and-test-py-project.sh" tags: - python3.5 except: - tags -Python 2.6: + +Python 3.7: script: - - py_version=2.6 - - EXTRA_INSTALL=numpy + - py_version=3.7 + - EXTRA_INSTALL="numpy pybind11" - curl -L -O -k https://gitlab.tiker.net/inducer/ci-support/raw/master/build-and-test-py-project.sh - ". ./build-and-test-py-project.sh" tags: - - python2.6 + - python3.7 except: - tags Documentation: script: - - EXTRA_INSTALL="numpy" + - EXTRA_INSTALL="numpy pybind11" - curl -L -O -k https://gitlab.tiker.net/inducer/ci-support/raw/master/build-docs.sh - ". ./build-docs.sh" tags: diff --git a/.gitmodules b/.gitmodules deleted file mode 100644 index f508bc2ef8322f96c51c1f7d4f594d0e3721692a..0000000000000000000000000000000000000000 --- a/.gitmodules +++ /dev/null @@ -1,3 +0,0 @@ -[submodule "bpl-subset"] - path = bpl-subset - url = git://github.com/inducer/bpl-subset diff --git a/MANIFEST.in b/MANIFEST.in index ea0c8f7ec50c9c93d35c8e5bb1d0c271ed636231..d8736d1a9593ebe7389e2d48e9689bb4bc8c8dc2 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -17,6 +17,3 @@ include configure.py include Makefile.in include aksetup_helper.py include README_SETUP.txt - -recursive-include bpl-subset/bpl_subset/boost *.h *.hpp *.cpp *.html *.inl *.ipp *.pl *.txt -recursive-include bpl-subset/bpl_subset/libs *.h *.hpp *.cpp *.html *.inl *.ipp *.pl *.txt diff --git a/bpl-subset b/bpl-subset deleted file mode 160000 index a44c81ff6251387d660a25b3c1c39a5639484079..0000000000000000000000000000000000000000 --- a/bpl-subset +++ /dev/null @@ -1 +0,0 @@ -Subproject commit a44c81ff6251387d660a25b3c1c39a5639484079 diff --git a/setup.py b/setup.py index f84d1e140c9e0084819a39ab8a5652495016445c..855d9c7b57628d581d4631414cc1cb711e580de1 100644 --- a/setup.py +++ b/setup.py @@ -1,75 +1,15 @@ #!/usr/bin/env python -import sys -import os - - -# {{{ use cmake to find boost - -def get_boost_defaults_from_cmake(): - boost_variables = ["VERSION", "INCLUDE_DIRS", "LIB_DIRS", "LIBRARIES"] - boost_dict = {} - - cmake_cmd = ["cmake", "."] - if sys.version_info < (3,): - cmake_cmd.append("-Dpy_version=2") - else: - cmake_cmd.append("-Dpy_version=3") - - from subprocess import Popen, PIPE - - boost_conf = {} - - try: - cmake = Popen(cmake_cmd, stdout=PIPE) - except OSError: - return boost_conf - - cmake_out, stderr_out = cmake.communicate() - - if cmake.returncode == 0: - for line in cmake_out.decode("utf-8").split("\n"): - for var in boost_variables: - if var in line: - line = (line - .replace('-- ' + var, '') - .replace(': ', '') - .replace('\n', '')) - boost_dict[var] = line - - else: - print("*** error return from cmake") - - if "VERSION" in boost_dict: - print("used cmake to detect boost") - bpl_lib_name = os.path.basename(boost_dict["LIBRARIES"]) - bpl_lib_name = (bpl_lib_name - .replace(".lib", "") - .replace("lib", "") - .replace(".so", "")) - boost_conf["BOOST_INC_DIR"] = [boost_dict["INCLUDE_DIRS"]] - boost_conf["BOOST_LIB_DIR"] = [boost_dict["LIB_DIRS"]] - boost_conf["BOOST_PYTHON_LIBNAME"] = bpl_lib_name - - return boost_conf - -# }}} +import sys +import setuptools +from setuptools import Extension +from setuptools.command.build_ext import build_ext def get_config_schema(): - from aksetup_helper import (ConfigSchema, - BoostLibraries, Switch, StringListOption, IncludeDir, LibraryDir) - - cmake_boost_conf = get_boost_defaults_from_cmake() + from aksetup_helper import (ConfigSchema, StringListOption) return ConfigSchema([ - IncludeDir("BOOST", cmake_boost_conf.get("BOOST_INC_DIR", [])), - LibraryDir("BOOST", cmake_boost_conf.get("BOOST_LIB_DIR", [])), - BoostLibraries("python", - default_lib_name=cmake_boost_conf.get("BOOST_PYTHON_LIBNAME")), - - Switch("USE_SHIPPED_BOOST", True, "Use included Boost library"), - StringListOption("CXXFLAGS", [], help="Any extra C++ compiler options to include"), StringListOption("LDFLAGS", [], @@ -77,36 +17,120 @@ def get_config_schema(): ]) +# {{{ pybind11 gunk + +class get_pybind_include(object): # noqa + """Helper class to determine the pybind11 include path + + The purpose of this class is to postpone importing pybind11 + until it is actually installed, so that the ``get_include()`` + method can be invoked. """ + + def __init__(self, user=False): + self.user = user + + def __str__(self): + import pybind11 + return pybind11.get_include(self.user) + + +ext_modules = [ + Extension( + 'python_example', + ['src/main.cpp'], + include_dirs=[ + # Path to pybind11 headers + get_pybind_include(), + get_pybind_include(user=True) + ], + language='c++' + ), +] + + +# As of Python 3.6, CCompiler has a `has_flag` method. +# cf http://bugs.python.org/issue26689 +def has_flag(compiler, flagname): + """Return a boolean indicating whether a flag name is supported on + the specified compiler. + """ + import tempfile + with tempfile.NamedTemporaryFile('w', suffix='.cpp') as f: + f.write('int main (int argc, char **argv) { return 0; }') + try: + compiler.compile([f.name], extra_postargs=[flagname]) + except setuptools.distutils.errors.CompileError: + return False + return True + + +def cpp_flag(compiler): + """Return the -std=c++[11/14] compiler flag. + + The c++14 is prefered over c++11 (when it is available). + """ + if has_flag(compiler, '-std=c++14'): + return '-std=c++14' + elif has_flag(compiler, '-std=c++11'): + return '-std=c++11' + else: + raise RuntimeError('Unsupported compiler -- at least C++11 support ' + 'is needed!') + + +class BuildExt(build_ext): + """A custom build extension for adding compiler-specific options.""" + c_opts = { + 'msvc': ['/EHsc'], + 'unix': [], + } + + if sys.platform == 'darwin': + c_opts['unix'] += ['-stdlib=libc++', '-mmacosx-version-min=10.7'] + + def build_extensions(self): + ct = self.compiler.compiler_type + opts = self.c_opts.get(ct, []) + if ct == 'unix': + opts.append('-DVERSION_INFO="%s"' % self.distribution.get_version()) + opts.append(cpp_flag(self.compiler)) + if has_flag(self.compiler, '-fvisibility=hidden'): + opts.append('-fvisibility=hidden') + elif ct == 'msvc': + opts.append('/DVERSION_INFO=\\"%s\\"' % self.distribution.get_version()) + for ext in self.extensions: + ext.extra_compile_args = opts + build_ext.build_extensions(self) + +# }}} + + def main(): from aksetup_helper import (hack_distutils, - get_config, setup, Extension, set_up_shipped_boost_if_requested, - check_git_submodules) + get_config, setup, check_git_submodules) check_git_submodules() hack_distutils(what_opt=1) conf = get_config(get_config_schema()) - TRI_EXTRA_OBJECTS, TRI_EXTRA_DEFINES = \ - set_up_shipped_boost_if_requested("meshpy", conf) - TET_EXTRA_OBJECTS, TET_EXTRA_DEFINES = TRI_EXTRA_OBJECTS, TRI_EXTRA_DEFINES - triangle_macros = [ ("EXTERNAL_TEST", 1), ("ANSI_DECLARATORS", 1), ("TRILIBRARY", 1), - ] + list(TRI_EXTRA_DEFINES.items()) + ] tetgen_macros = [ ("TETLIBRARY", 1), ("SELF_CHECK", 1), - ] + list(TET_EXTRA_DEFINES.items()) + ] # }}} - include_dirs = conf["BOOST_INC_DIR"] + ["src/cpp"] - library_dirs = conf["BOOST_LIB_DIR"] - libraries = conf["BOOST_PYTHON_LIBNAME"] + include_dirs = [ + get_pybind_include(), + get_pybind_include(user=True) + ] + ["src/cpp"] init_filename = "meshpy/__init__.py" exec(compile(open(init_filename, "r").read(), init_filename, "exec"), conf) @@ -131,7 +155,6 @@ def main(): 'Natural Language :: English', 'Programming Language :: C++', 'Programming Language :: Python', - 'Programming Language :: Python :: 2.6', 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3', 'Programming Language :: Python :: 3.2', @@ -146,6 +169,7 @@ def main(): ], packages=["meshpy"], + setup_requires=["pybind11"], install_requires=[ "pytools>=2011.2", "pytest>=2", @@ -156,11 +180,8 @@ def main(): ext_modules=[ Extension( "meshpy._triangle", - ["src/cpp/wrap_triangle.cpp", "src/cpp/triangle.c"] - + TRI_EXTRA_OBJECTS, + ["src/cpp/wrap_triangle.cpp", "src/cpp/triangle.c"], include_dirs=include_dirs, - library_dirs=library_dirs, - libraries=libraries, define_macros=triangle_macros, extra_compile_args=conf["CXXFLAGS"], extra_link_args=conf["LDFLAGS"], @@ -170,16 +191,16 @@ def main(): [ "src/cpp/tetgen.cpp", "src/cpp/predicates.cpp", - "src/cpp/wrap_tetgen.cpp"] - + TET_EXTRA_OBJECTS, + "src/cpp/wrap_tetgen.cpp"], include_dirs=include_dirs, - library_dirs=library_dirs, - libraries=libraries, define_macros=tetgen_macros, extra_compile_args=conf["CXXFLAGS"], extra_link_args=conf["LDFLAGS"], ), - ]) + ], + cmdclass={'build_ext': BuildExt}, + zip_safe=False, + ) if __name__ == '__main__': diff --git a/src/cpp/foreign_array.hpp b/src/cpp/foreign_array.hpp index 31f3b49ded9cb1b4a27d92cd7ea2eb256a14614e..56bb4ca9bdcdd6a02e876cbfff2d15af8e5080d7 100644 --- a/src/cpp/foreign_array.hpp +++ b/src/cpp/foreign_array.hpp @@ -6,10 +6,21 @@ #include #include -#include -namespace{ +// https://stackoverflow.com/a/44175911 +class noncopyable { +public: + noncopyable() = default; + ~noncopyable() = default; + +private: + noncopyable(const noncopyable&) = delete; + noncopyable& operator=(const noncopyable&) = delete; +}; + + +namespace { class tSizeChangeNotifier; @@ -70,7 +81,7 @@ class tSizeChangeNotifier template class tReadOnlyForeignArray : public tSizeChangeNotifier, public tSizeChangeNotificationReceiver, - public boost::noncopyable + public noncopyable { protected: ElementT *&Contents; diff --git a/src/cpp/foreign_array_wrap.hpp b/src/cpp/foreign_array_wrap.hpp index 9ef3c5257844959222263a18d91b34f92f340b36..f94751db107507ea20c5ee6a8b412c85d27ce638 100644 --- a/src/cpp/foreign_array_wrap.hpp +++ b/src/cpp/foreign_array_wrap.hpp @@ -5,12 +5,7 @@ #include "foreign_array.hpp" -#include - - - - -using namespace boost::python; +#include @@ -18,7 +13,7 @@ using namespace boost::python; #define PYTHON_ERROR(TYPE, REASON) \ { \ PyErr_SetString(PyExc_##TYPE, REASON); \ - throw error_already_set(); \ + throw pybind11::error_already_set(); \ } @@ -26,7 +21,7 @@ namespace { /* This wrap helper works as long as the value_type is a plain old data (POD) * type. * - * In exchange for this, it nicely wraps the "unit" abstraction provided by + * In exchange for this, it nicely wraps the "unit" abstraction provided by * foreign arrays. */ template @@ -34,70 +29,68 @@ namespace { { typedef typename FA::value_type value_type; - static object getitem(FA &self, long idx) + static pybind11::object getitem(FA &self, long idx) { if (idx < 0) idx += self.size(); - if (idx < 0 || idx >= (long) self.size()) + if (idx < 0 || idx >= (long) self.size()) PYTHON_ERROR(IndexError, "index out of bounds"); - + if (self.unit() > 1) { - list l; + pybind11::list l; for (unsigned i = 0; i(idx[0]); - long i_sub = extract(idx[1]); + long i_main = pybind11::cast(idx[0]); + long i_sub = pybind11::cast(idx[1]); - if (i_main < 0) idx += self.size(); - if (i_main < 0 || i_main >= (long) self.size()) + if (i_main < 0 || i_main >= (long) self.size()) PYTHON_ERROR(IndexError, "index out of bounds"); - if (i_sub < 0) idx += self.unit(); - if (i_sub < 0 || i_sub >= (long) self.unit()) + if (i_sub < 0 || i_sub >= (long) self.unit()) PYTHON_ERROR(IndexError, "subindex out of bounds"); - return object(self.getSub(i_main, i_sub)); + return pybind11::cast(self.getSub(i_main, i_sub)); } - static void setitem(FA &self, long idx, object value) + static void setitem(FA &self, long idx, pybind11::object value) { if (idx < 0) idx += self.size(); - if (idx < 0 || idx >= (long) self.size()) + if (idx < 0 || idx >= (long) self.size()) PYTHON_ERROR(IndexError, "index out of bounds"); if (self.unit() > 1) { - if ((long) self.unit() != len(value)) + pybind11::sequence value_seq = pybind11::cast(value); + + if ((long) self.unit() != len(value)) PYTHON_ERROR(ValueError, "value must be a sequence of length self.unit"); - - for (long i = 0; i(value[i])); + + for (size_t i = 0; i(value_seq[i])); } else - self.set(idx, extract(value)); + self.set(idx, pybind11::cast(value)); } - static void setitem(FA &self, boost::python::tuple idx, const value_type &v) + static void setitem_tup(FA &self, pybind11::tuple idx, const value_type &v) { if (len(idx) != 2) PYTHON_ERROR(IndexError, "expected index tuple of length 2"); - long i_main = extract(idx[0]); - long i_sub = extract(idx[1]); + long i_main = pybind11::cast(idx[0]); + long i_sub = pybind11::cast(idx[1]); - if (i_main < 0) idx += self.size(); - if (i_main < 0 || i_main >= (long) self.size()) + if (i_main < 0 || i_main >= (long) self.size()) PYTHON_ERROR(IndexError, "index out of bounds"); - if (i_sub < 0) idx += self.unit(); - if (i_main < 0 || i_sub >= (long) self.unit()) + if (i_main < 0 || i_sub >= (long) self.unit()) PYTHON_ERROR(IndexError, "subindex out of bounds"); self.setSub(i_main, i_sub, v); @@ -122,7 +115,7 @@ namespace { { if (idx < 0) idx += self.size(); if (idx >= (long) self.size()) PYTHON_ERROR(IndexError, "index out of bounds"); - + return self.get(idx); } }; @@ -132,22 +125,21 @@ namespace { template -void exposePODForeignArray(const std::string &name) +void exposePODForeignArray(pybind11::module &m,const std::string &name) { typedef tForeignArray cl; typedef tPODForeignArrayWrapHelper w_cl; - typedef typename cl::value_type value_type; - boost::python::class_(name.c_str(), no_init) + pybind11::class_(m, name.c_str()) .def("__len__", &cl::size) .def("resize", &cl::setSize) .def("setup", &cl::setup) - .add_property("unit", &cl::unit) - .add_property("allocated", &cl::is_allocated) - .def("__getitem__", (object (*)(cl &, long)) &w_cl::getitem) - .def("__getitem__", (object (*)(cl &, boost::python::tuple)) &w_cl::getitem) - .def("__setitem__", (void (*)(cl &, long, object)) &w_cl::setitem) - .def("__setitem__", (void (*)(cl &, boost::python::tuple, const value_type &)) &w_cl::setitem) + .def_property_readonly("unit", &cl::unit) + .def_property_readonly("allocated", &cl::is_allocated) + .def("__getitem__", &w_cl::getitem) + .def("__getitem__", &w_cl::getitem_tup) + .def("__setitem__", &w_cl::setitem) + .def("__setitem__", &w_cl::setitem_tup) .def("deallocate", &cl::deallocate) ; } @@ -157,19 +149,18 @@ void exposePODForeignArray(const std::string &name) template -void exposeStructureForeignArray(const std::string &name) +void exposeStructureForeignArray(pybind11::module &m, const std::string &name) { typedef tForeignArray cl; typedef tStructureForeignArrayWrapHelper w_cl; - typedef typename cl::value_type value_type; - boost::python::class_(name.c_str(), no_init) + pybind11::class_(m, name.c_str()) .def("__len__", &cl::size) .def("resize", &cl::setSize) .def("setup", &cl::setup) - .add_property("unit", &cl::unit) - .add_property("allocated", &cl::is_allocated) - .def("__getitem__", &w_cl::getitem, return_internal_reference<>()) + .def_property_readonly("unit", &cl::unit) + .def_property_readonly("allocated", &cl::is_allocated) + .def("__getitem__", &w_cl::getitem, pybind11::return_value_policy::reference_internal) .def("deallocate", &cl::deallocate) ; } diff --git a/src/cpp/wrap_tetgen.cpp b/src/cpp/wrap_tetgen.cpp index 231f9fdae768e7fca4c8ce7a24987afe75438a4c..2c715b30f351f9db3c1dbb4f02df151cf9f5a1a8 100644 --- a/src/cpp/wrap_tetgen.cpp +++ b/src/cpp/wrap_tetgen.cpp @@ -1,6 +1,5 @@ #include "tetgen.h" -#include -#include +#include #include #include #include @@ -9,36 +8,13 @@ -using namespace boost::python; -namespace py = boost::python; +namespace py = pybind11; using namespace std; -namespace boost { -template <> -inline tForeignArray const volatile * get_pointer(class tForeignArray const volatile *tF) { - return tF; -} - -template <> -inline tForeignArray const volatile * get_pointer(class tForeignArray const volatile *tF) { - return tF; -} - -template <> -inline tForeignArray const volatile * get_pointer(class tForeignArray const volatile *tF) { - return tF; -} - -template <> -inline tForeignArray const volatile * get_pointer(class tForeignArray const volatile *tF) { - return tF; -} -} - namespace { - struct tMeshInfo : public tetgenio, public boost::noncopyable + struct tMeshInfo : public tetgenio, public noncopyable { private: typedef tetgenio super; @@ -241,7 +217,7 @@ namespace } catch (int &i) { - throw runtime_error("TetGen runtime error code "+boost::lexical_cast(i)); + throw runtime_error("TetGen runtime error code "+std::to_string(i)); } out.Elements.fixUnit(out.numberofcorners); @@ -253,16 +229,6 @@ namespace - template - struct manage_new_internal_reference - : with_custodian_and_ward_postcall<0, owner_arg, Base> - { - typedef manage_new_object result_converter; - }; - - - - tForeignArray *facet_get_polygons(tetgenio::facet &self) { return new tForeignArray( @@ -296,15 +262,16 @@ namespace #define DEF_METHOD(NAME) \ def(#NAME, &cl::NAME) -BOOST_PYTHON_MODULE(_tetgen) +PYBIND11_MODULE(_tetgen, m) { - def("tetrahedralize", tetrahedralizeWrapper, - (py::args("behavior", "in", "out"), py::arg("addin")=py::object())); + m.def("tetrahedralize", tetrahedralizeWrapper, + py::arg("behavior"), py::arg("in"), py::arg("out"), + py::arg("addin").none(true)=py::none()); { typedef tMeshInfo cl; - class_ - ("MeshInfo", init<>()) + py::class_(m, "MeshInfo") + .def(py::init<>()) .def_readonly("points", &cl::Points) .def_readonly("point_attributes", &cl::PointAttributes) .def_readonly("point_metric_tensors", &cl::PointMetricTensors) @@ -334,13 +301,13 @@ BOOST_PYTHON_MODULE(_tetgen) .def_readonly("edge_markers", &cl::EdgeMarkers) .def_readonly("edge_adjacent_elements", &cl::EdgeAdjTetList) - .add_property("number_of_point_attributes", + .def_property("number_of_point_attributes", &cl::numberOfPointAttributes, &cl::setNumberOfPointAttributes) - .add_property("number_of_element_vertices", + .def_property("number_of_element_vertices", &cl::numberOfElementVertices, &cl::setNumberOfElementVertices) - .add_property("number_of_element_attributes", + .def_property("number_of_element_attributes", &cl::numberOfElementAttributes, &cl::setNumberOfElementAttributes) @@ -372,25 +339,26 @@ BOOST_PYTHON_MODULE(_tetgen) { typedef tetgenio::facet cl; - class_("Facet", no_init) - .add_property("polygons", - make_function(facet_get_polygons, manage_new_internal_reference<>())) - .add_property("holes", - make_function(facet_get_holes, manage_new_internal_reference<>())) + py::class_(m, "Facet") + .def_property_readonly("polygons", + facet_get_polygons, py::return_value_policy::reference_internal) + .def_property_readonly("holes", + facet_get_holes, py::return_value_policy::reference_internal) ; } { typedef tetgenio::polygon cl; - class_("Polygon", no_init) - .add_property("vertices", - make_function(polygon_get_vertices, manage_new_internal_reference<>())) + py::class_(m, "Polygon") + .def_property_readonly("vertices", + polygon_get_vertices, py::return_value_policy::reference_internal) ; } { typedef tetgenbehavior cl; - class_("Options", init<>()) + py::class_(m, "Options") + .def(py::init<>()) .DEF_RW_MEMBER(plc) .DEF_RW_MEMBER(psc) .DEF_RW_MEMBER(refine) @@ -467,8 +435,8 @@ BOOST_PYTHON_MODULE(_tetgen) ; } - exposePODForeignArray("RealArray"); - exposePODForeignArray("IntArray"); - exposeStructureForeignArray("FacetArray"); - exposeStructureForeignArray("PolygonArray"); + exposePODForeignArray(m, "RealArray"); + exposePODForeignArray(m, "IntArray"); + exposeStructureForeignArray(m, "FacetArray"); + exposeStructureForeignArray(m, "PolygonArray"); } diff --git a/src/cpp/wrap_triangle.cpp b/src/cpp/wrap_triangle.cpp index 6aea449e7599b27fcc57217e02cdd65643792ec3..4857345ff410d82e3e55bbd8b022b85c68e9ba25 100644 --- a/src/cpp/wrap_triangle.cpp +++ b/src/cpp/wrap_triangle.cpp @@ -1,16 +1,16 @@ #include "triangle.h" -#include +#include #include #include +#include #include "foreign_array_wrap.hpp" +namespace py = pybind11; - - -using namespace boost::python; using namespace std; +/* namespace boost { template <> inline tForeignArray const volatile * get_pointer(class tForeignArray const volatile *tF) { @@ -22,10 +22,11 @@ inline tForeignArray const volatile * get_pointer(class tForeignArray Points; // in/out @@ -135,7 +136,7 @@ struct tMeshInfo : public triangulateio, public boost::noncopyable tMeshInfo *copyMesh(const tMeshInfo &src) { - auto_ptr copy(new tMeshInfo); + std::unique_ptr copy(new tMeshInfo); *copy = src; return copy.release(); } @@ -148,7 +149,7 @@ PyObject *RefinementFunction; -class tVertex : public boost::noncopyable +class tVertex : public noncopyable { public: REAL *Data; @@ -185,16 +186,17 @@ int triunsuitable(vertex triorg, vertex tridest, vertex triapex, REAL area) tVertex dest(tridest); tVertex apex(triapex); + py::handle refine_func = py::reinterpret_borrow(RefinementFunction); + try { - return call(RefinementFunction, - boost::python::make_tuple( - object(boost::ref(org)), - object(boost::ref(dest)), - object(boost::ref(apex)) - ), area); + return py::cast(refine_func( + py::make_tuple( + py::cast(org, py::return_value_policy::reference), + py::cast(dest, py::return_value_policy::reference), + py::cast(apex, py::return_value_policy::reference)), area)); } - catch (error_already_set) + catch (py::error_already_set &) { std::cout << "[MeshPy warning] A Python exception occurred in " "a Python refinement query:" << std::endl; @@ -218,9 +220,9 @@ int triunsuitable(vertex triorg, vertex tridest, vertex triapex, REAL area) void triangulateWrapper(char *options, tMeshInfo &in, tMeshInfo &out, tMeshInfo &voronoi, - PyObject *refinement_func) + py::object refinement_func) { - RefinementFunction = refinement_func; + RefinementFunction = refinement_func.ptr(); triangulate(options, &in, &out, &voronoi); out.holelist = NULL; @@ -237,14 +239,14 @@ void triangulateWrapper(char *options, tMeshInfo &in, -BOOST_PYTHON_MODULE(_triangle) +PYBIND11_MODULE(_triangle, m) { - def("triangulate", triangulateWrapper); + m.def("triangulate", triangulateWrapper); { typedef tMeshInfo cl; - class_ - ("MeshInfo", init<>()) + py::class_(m, "MeshInfo") + .def(py::init<>()) .def_readonly("points", &cl::Points) .def_readonly("point_attributes", &cl::PointAttributes) .def_readonly("point_markers", &cl::PointMarkers) @@ -266,26 +268,26 @@ BOOST_PYTHON_MODULE(_triangle) .def_readonly("normals", &cl::Normals) - .add_property("number_of_point_attributes", + .def_property("number_of_point_attributes", &cl::numberOfPointAttributes, &cl::setNumberOfPointAttributes) - .add_property("number_of_element_attributes", + .def_property("number_of_element_attributes", &cl::numberOfElementAttributes, &cl::setNumberOfElementAttributes) - .def("copy", ©Mesh, return_value_policy()) - .enable_pickling() + .def("copy", ©Mesh) + // .enable_pickling() ; } - exposePODForeignArray("RealArray"); - exposePODForeignArray("IntArray"); + exposePODForeignArray(m, "RealArray"); + exposePODForeignArray(m, "IntArray"); { typedef tVertex cl; - class_("Vertex", no_init) - .add_property("x", &cl::x) - .add_property("y", &cl::y) + py::class_(m, "Vertex") + .def_property_readonly("x", &cl::x) + .def_property_readonly("y", &cl::y) .def("__len__", &cl::size) .def("__getitem__", &cl::operator[]) ;