diff --git a/CMakeLists.txt b/CMakeLists.txt index 6543e48003..5e9e2870d8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,8 +4,8 @@ set( CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS TRUE ) # Define here the needed parameters set (OPENRAVE_VERSION_MAJOR 0) -set (OPENRAVE_VERSION_MINOR 83) -set (OPENRAVE_VERSION_PATCH 2) +set (OPENRAVE_VERSION_MINOR 84) +set (OPENRAVE_VERSION_PATCH 0) set (OPENRAVE_VERSION ${OPENRAVE_VERSION_MAJOR}.${OPENRAVE_VERSION_MINOR}.${OPENRAVE_VERSION_PATCH}) set (OPENRAVE_SOVERSION ${OPENRAVE_VERSION_MAJOR}.${OPENRAVE_VERSION_MINOR}) message(STATUS "Compiling OpenRAVE Version ${OPENRAVE_VERSION}, soversion=${OPENRAVE_SOVERSION}") diff --git a/plugins/configurationcache/CMakeLists.txt b/plugins/configurationcache/CMakeLists.txt index b1d1c84c2b..0e4b7c40d0 100644 --- a/plugins/configurationcache/CMakeLists.txt +++ b/plugins/configurationcache/CMakeLists.txt @@ -8,7 +8,7 @@ set_target_properties(configurationcache PROPERTIES COMPILE_FLAGS "${PLUGIN_COMP install(TARGETS configurationcache DESTINATION ${OPENRAVE_PLUGINS_INSTALL_DIR} COMPONENT ${PLUGINS_BASE}) # python bindings -if( HAVE_ALL_PYTHON_HEADERS ) +if( OPT_PYTHON AND HAVE_ALL_PYTHON_HEADERS ) # include include_directories(${PYTHON_INCLUDE_PATH} ${PYTHON_INCLUDE_DIRS} ${OPENRAVE_CORE_INCLUDE_LOCAL_DIRS} ${OPENRAVEPY_INCLUDE_LOCAL_DIRS} diff --git a/python/bindings/include/openravepy/openravepy_int.h b/python/bindings/include/openravepy/openravepy_int.h index 9d8989e59f..cc31f1bfca 100644 --- a/python/bindings/include/openravepy/openravepy_int.h +++ b/python/bindings/include/openravepy/openravepy_int.h @@ -203,6 +203,8 @@ class OPENRAVEPY_API PythonThreadSaver PyThreadState *_save; }; +typedef OPENRAVE_SHARED_PTR PythonThreadSaverPtr; + /// \brief release and restore the python GIL... no thread state saved..? class OPENRAVEPY_API PythonGILSaver { @@ -215,20 +217,62 @@ class OPENRAVEPY_API PythonGILSaver } }; -class OPENRAVEPY_API AutoPyArrayObjectDereferencer +template +class OPENRAVEPY_API PyCapsule { public: - AutoPyArrayObjectDereferencer(PyArrayObject* pyarrobj) : _pyarrobj(pyarrobj) { + // \brief disables copy constructor to avoid calling Py_DECREF more than once + PyCapsule(const PyCapsule&) = delete; + + // \brief the only entrypoint that allows a nullptr. Expects a `reset` call to follow + PyCapsule() + : _ptr(nullptr) + { + } + + // \param ptr a not-null pointer + PyCapsule(T* ptr) + : _ptr(_PreventNullPtr(ptr)) + { + } + + // \param ptr a not-null pointer + void reset(T* ptr) + { + _ptr = _PreventNullPtr(ptr); + } + + T* get() const + { + return _ptr; + } + + operator T*() const + { + return _ptr; } - ~AutoPyArrayObjectDereferencer() { - Py_DECREF(_pyarrobj); + + ~PyCapsule() { + if (_ptr != nullptr) { + Py_DECREF(_ptr); + } } private: - PyArrayObject* _pyarrobj; + T* _ptr; + + static T* _PreventNullPtr(T* ptr) + { + if (ptr == nullptr) { + throw OPENRAVE_EXCEPTION_FORMAT0(_("Invalid Numpy-array pointer. Failed to get contiguous array?"), ORE_InvalidArguments); + } + return ptr; + } }; -typedef OPENRAVE_SHARED_PTR PythonThreadSaverPtr; +typedef PyCapsule PyArrayCapsule; + +typedef PyArrayCapsule AutoPyArrayObjectDereferencer; // Backwards compatibility inline RaveVector ExtractFloat3(const py::object& o) { diff --git a/python/bindings/openravepy_global.cpp b/python/bindings/openravepy_global.cpp index 87de87cf6f..0dbeccc35d 100644 --- a/python/bindings/openravepy_global.cpp +++ b/python/bindings/openravepy_global.cpp @@ -350,8 +350,7 @@ class PyTriMesh if (!PyArray_ISFLOAT(pPyVertices)) { throw openrave_exception(_("vertices must be in float"), ORE_InvalidArguments); } - PyArrayObject* pPyVerticesContiguous = PyArray_GETCONTIGUOUS(reinterpret_cast(pPyVertices)); - AutoPyArrayObjectDereferencer pydecref(pPyVerticesContiguous); + PyArrayCapsule pPyVerticesContiguous(PyArray_GETCONTIGUOUS(reinterpret_cast(pPyVertices))); const size_t typeSize = PyArray_ITEMSIZE(pPyVerticesContiguous); const size_t n = PyArray_DIM(pPyVerticesContiguous, 0); @@ -393,8 +392,7 @@ class PyTriMesh if (PyArray_NDIM(pPyIndices) != 2 || PyArray_DIM(pPyIndices, 1) != 3 || !PyArray_ISINTEGER(pPyIndices)) { throw openrave_exception(_("indices must be a Nx3 int array"), ORE_InvalidArguments); } - PyArrayObject* pPyIndiciesContiguous = PyArray_GETCONTIGUOUS(reinterpret_cast(pPyIndices)); - AutoPyArrayObjectDereferencer pydecref(pPyIndiciesContiguous); + PyArrayCapsule pPyIndiciesContiguous(PyArray_GETCONTIGUOUS(reinterpret_cast(pPyIndices))); const size_t typeSize = PyArray_ITEMSIZE(pPyIndiciesContiguous); const bool signedInt = PyArray_ISSIGNED(pPyIndiciesContiguous); diff --git a/python/bindings/openravepy_int.cpp b/python/bindings/openravepy_int.cpp index ddd1905bdb..4a0d9855b8 100644 --- a/python/bindings/openravepy_int.cpp +++ b/python/bindings/openravepy_int.cpp @@ -300,8 +300,7 @@ void toRapidJSONValue(const object &obj, rapidjson::Value &value, rapidjson::Doc #endif // USE_PYBIND11_PYTHON_BINDINGS } else if (PyArray_Check(obj.ptr()) ) { - PyArrayObject* pyarrayvalues = PyArray_GETCONTIGUOUS(reinterpret_cast(obj.ptr())); - AutoPyArrayObjectDereferencer pydecref(pyarrayvalues); + PyArrayCapsule pyarrayvalues(PyArray_GETCONTIGUOUS(reinterpret_cast(obj.ptr()))); int ndims = PyArray_NDIM(pyarrayvalues); npy_intp* dims = PyArray_DIMS(pyarrayvalues); @@ -1586,8 +1585,7 @@ object PyEnvironmentBase::CheckCollisionRays(py::numeric::array rays, PyKinBodyP CollisionReport report; CollisionReportPtr preport(&report,null_deleter()); - PyArrayObject *pPyRays = PyArray_GETCONTIGUOUS(reinterpret_cast(rays.ptr())); - AutoPyArrayObjectDereferencer pyderef(pPyRays); + PyArrayCapsule pPyRays(PyArray_GETCONTIGUOUS(reinterpret_cast(rays.ptr()))); if( !PyArray_ISFLOAT(pPyRays) ) { throw OpenRAVEException(_("rays has to be a float array\n"));