Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add nanobind Python bindings #439

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions .github/workflows/ci_workflow.yml
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,36 @@ jobs:
pybind11: 'ON'
python-desc: python3.11
vfx-cy: 2024

# -------------------------------------------------------------------
# nanobind and python together
# -------------------------------------------------------------------
- build: 10
build-type: Release
build-shared: 'ON'
cxx-standard: 17
cxx-compiler: g++
cc-compiler: gcc
compiler-desc: gcc11.2.1
python: 'ON'
nanobind: 'ON'
python-desc: python3.11
vfx-cy: 2024

# -------------------------------------------------------------------
# nanobind w/o python
# -------------------------------------------------------------------
- build: 11
build-type: Release
build-shared: 'ON'
cxx-standard: 17
cxx-compiler: g++
cc-compiler: gcc
compiler-desc: gcc11.2.1
python: 'OFF'
nanobind: 'ON'
python-desc: python3.11
vfx-cy: 2024
env:
CXX: ${{ matrix.cxx-compiler }}
CC: ${{ matrix.cc-compiler }}
Expand All @@ -241,6 +271,7 @@ jobs:
-DBUILD_SHARED_LIBS=${{ matrix.build-shared }} \
-DPYTHON=${{ matrix.python }} \
-DPYBIND11=${{ matrix.pybind11 }} \
-DNANOBIND=${{ matrix.nanobind }} \
-DUSE_PYTHON2=${{ matrix.use-python2 }}
working-directory: _build
- name: Build
Expand Down Expand Up @@ -289,6 +320,10 @@ jobs:
export PYTHONPATH=`find ../_install -name 'pybindimath.*.so' | xargs dirname`
python -c "import pybindimath;print(pybindimath.__version__)"
fi
if [[ "${{ matrix.nanobind }}" == "ON" ]]; then
export PYTHONPATH=`find ../_install -name 'nanobindimath.*.so' | xargs dirname`
python -c "import nanobindimath;print(nanobindimath.__version__)"
fi
shell: bash
working-directory: _build
- name: Test
Expand Down
6 changes: 5 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,11 @@ if (PYBIND11)
add_subdirectory(src/pybind11)
endif()

option(NANOBIND "Set ON to compile nanobind PyImath bindings")
if (NANOBIND)
add_subdirectory(src/nanobind)
endif()

option(BUILD_WEBSITE "Set ON to build the readthedocs website source")
if (BUILD_WEBSITE AND NOT IMATH_IS_SUBPROJECT)
add_subdirectory(website)
Expand Down Expand Up @@ -119,4 +124,3 @@ endif()
if(NOT IMATH_IS_SUBPROJECT)
include(cmake/clang-format.cmake)
endif()

17 changes: 17 additions & 0 deletions src/nanobind/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# SPDX-License-Identifier: BSD-3-Clause
# Copyright Contributors to the OpenEXR Project.

set(NANOBINDIMATH_OVERRIDE_PYTHON_INSTALL_DIR "" CACHE STRING "Override the install location for imath.so and imathnumpy.so modules")

########################
## Build related options

# Suffix to append to root name, this helps with version management
# but can be turned off if you don't care, or otherwise customized
#
set(NANOBINDIMATH_LIB_SUFFIX "-${IMATH_VERSION_API}" CACHE STRING "String added to the end of all the libraries")
# This provides a root for the unique name of the library based on
# the version of python being compiled for
set(NANOBINDIMATH_LIB_PYTHONVER_ROOT "_Python" CACHE STRING "String added as a root to the identifier of the python version in the libraries")

add_subdirectory(NanobindImath)
109 changes: 109 additions & 0 deletions src/nanobind/NanobindImath/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
# SPDX-License-Identifier: BSD-3-Clause
# Copyright Contributors to the OpenEXR Project.

find_package(Python REQUIRED COMPONENTS Interpreter Development)
find_package(Python3 REQUIRED COMPONENTS Interpreter Development)
find_package(nanobind REQUIRED)

#
# Source/headers
#

set(NANOBINDIMATH_SOURCES
NanobindImathBox.cpp
NanobindImathVec.cpp
)

set(NANOBINDIMATH_HEADERS
NanobindImathExport.h
NanobindImath.h
)

#
# shared library, e.g. libNanobindImath_Python3_11-3_2.so.30.3.2.0
#

set(NANOBINDIMATH_LIBRARY NanobindImath)

add_library(${NANOBINDIMATH_LIBRARY} SHARED ${NANOBINDIMATH_SOURCES})

nanobind_build_library(nanobind-static)

target_link_libraries(${NANOBINDIMATH_LIBRARY} PRIVATE Imath::Imath nanobind-static)

# Set include directories
target_include_directories(${NANOBINDIMATH_LIBRARY} PRIVATE ${Python3_INCLUDE_DIRS} ${Imath_INCLUDE_DIRS})

if(NOT "${NANOBINDIMATH_LIB_PYTHONVER_ROOT}" STREQUAL "")
set(pythonver_root "${NANOBINDIMATH_LIB_PYTHONVER_ROOT}${Python3_VERSION_MAJOR}_${Python3_VERSION_MINOR}")
message("pythonver_root ${NANOBINDIMATH_LIB_PYTHONVER_ROOT}${Python3_VERSION_MAJOR}_${Python3_VERSION_MINOR}")
endif()

if(BUILD_SHARED_LIBS)
# This creates the so-versioned library symlinks
set_target_properties(${NANOBINDIMATH_LIBRARY} PROPERTIES
SOVERSION ${IMATH_LIB_SOVERSION}
VERSION ${IMATH_LIB_VERSION}
OUTPUT_NAME "${NANOBINDIMATH_CURLIB_OUTROOT}${NANOBINDIMATH_LIBRARY}${pythonver_root}${NANOBINDIMATH_LIB_SUFFIX}"
)
endif()

#
# python module, e.g. nanobindimath.cpython-311-x86_64-linux-gnu.so
#

set(NANOBINDIMATH_MODULE nanobindimath)

nanobind_add_module(nanobindimath MODULE nanobindimathmodule.cpp $<TARGET_OBJECTS:${NANOBINDIMATH_LIBRARY}>)

target_link_libraries(${NANOBINDIMATH_MODULE} PRIVATE Imath::Imath)

if(SKBUILD)
set(PYTHON_INSTALL_DIR ${SKBUILD_PLATLIB_DIR})
else()
set(PYTHON_INSTALL_DIR "lib/python${Python3_VERSION_MAJOR}.${Python3_VERSION_MINOR}/site-packages")
endif()

if (IMATH_INSTALL)

# module

install(TARGETS ${NANOBINDIMATH_MODULE} DESTINATION ${PYTHON_INSTALL_DIR} COMPONENT python)

# shared library

install(TARGETS ${NANOBINDIMATH_LIBRARY}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})

if(BUILD_SHARED_LIBS AND (NOT "${IMATH_LIB_SUFFIX}" STREQUAL "") AND IMATH_INSTALL_SYM_LINK)

# create symlinks for the shared object so versions

string(TOUPPER "${CMAKE_BUILD_TYPE}" uppercase_CMAKE_BUILD_TYPE)
set(verlibname ${CMAKE_SHARED_LIBRARY_PREFIX}${NANOBINDIMATH_LIBRARY}${pythonver_root}${IMATH_LIB_SUFFIX}${CMAKE_${uppercase_CMAKE_BUILD_TYPE}_POSTFIX}${CMAKE_SHARED_LIBRARY_SUFFIX})
set(baselibname ${CMAKE_SHARED_LIBRARY_PREFIX}${NANOBINDIMATH_LIBRARY}${pythonver_root}${CMAKE_${uppercase_CMAKE_BUILD_TYPE}_POSTFIX}${CMAKE_SHARED_LIBRARY_SUFFIX})
file(CREATE_LINK ${verlibname} ${CMAKE_CURRENT_BINARY_DIR}/${baselibname} SYMBOLIC)
if(WIN32)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${baselibname} DESTINATION ${CMAKE_INSTALL_FULL_BINDIR})
install(CODE "message(STATUS \"Creating symlink ${CMAKE_INSTALL_FULL_BINDIR}/${baselibname} -> ${verlibname}\")")
else()
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${baselibname} DESTINATION ${CMAKE_INSTALL_FULL_LIBDIR})
install(CODE "message(STATUS \"Creating symlink ${CMAKE_INSTALL_FULL_LIBDIR}/${baselibname} -> ${verlibname}\")")
endif()
endif()

# pkgconfig

set(pcinfile NanobindImath.pc.in)
set(prefix ${CMAKE_INSTALL_PREFIX})
set(exec_prefix "\${prefix}")
set(libdir "\${exec_prefix}/${CMAKE_INSTALL_LIBDIR}")
set(includedir "\${prefix}/${CMAKE_INSTALL_INCLUDEDIR}")
string(REPLACE ".in" "" pcout ${pcinfile})
configure_file(${pcinfile} ${CMAKE_CURRENT_BINARY_DIR}/${pcout} @ONLY)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${pcout} DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig)

endif()
22 changes: 22 additions & 0 deletions src/nanobind/NanobindImath/NanobindImath.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
//
// SPDX-License-Identifier: BSD-3-Clause
// Copyright Contributors to the OpenEXR Project.
//

// clang-format off

#include <nanobind/nanobind.h>
#include <nanobind/operators.h>
#include "NanobindImathExport.h"

#ifndef _NanobindImath_h_
#define _NanobindImath_h_

namespace NanobindImath {

NANOBINDIMATH_EXPORT void register_imath_vec(nanobind::module_& m);
NANOBINDIMATH_EXPORT void register_imath_box(nanobind::module_& m);

}

#endif
17 changes: 17 additions & 0 deletions src/nanobind/NanobindImath/NanobindImath.pc.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
##
## SPDX-License-Identifier: BSD-3-Clause
## Copyright Contributors to the OpenEXR Project.
##

prefix=@prefix@
exec_prefix=@exec_prefix@
libdir=@libdir@
includedir=@includedir@
pythonver=@pythonver_root@

Name: NanobindImath
Description: nanobind-based python bindings for the Imath libraries
Version: @IMATH_VERSION@
Libs: -L${libdir} -lImath${libsuffix} -lNanobindImath${pythonver$}${libsuffix}

Cflags: -I${includedir} -I${includedir}/Imath
60 changes: 60 additions & 0 deletions src/nanobind/NanobindImath/NanobindImathBox.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
//
// SPDX-License-Identifier: BSD-3-Clause
// Copyright Contributors to the OpenEXR Project.
//

#include "NanobindImath.h"
#include <ImathBox.h>

namespace NanobindImath {

template <class T, class V>
void register_box(nanobind::class_<T>& c)
{
c.def(nanobind::init<>())
.def(nanobind::init<const V &>())
.def(nanobind::init<const V &, const V &>())
.def(nanobind::self == nanobind::self)
.def(nanobind::self != nanobind::self)
.def("makeEmpty", &T::makeEmpty, "makeEmpty() make the box empty")
.def("makeInfinite", &T::makeInfinite, "makeInfinite() make the box cover all space")
.def_rw("min", &T::min)
.def_rw("max", &T::max)
.def("extendBy", nanobind::overload_cast<const T &>(&T::extendBy), "extendBy(point) extend the box by a box")
.def("extendBy", nanobind::overload_cast<const V &>(&T::extendBy), "extendBy(point) extend the box by a point")
.def("size", &T::size, "size() size of the box")
.def("center", &T::center, "center() center of the box")
.def("intersects",nanobind::overload_cast<const V &>(&T::extendBy), "intersects(point) returns true if the box intersects the given point")
.def("intersects",nanobind::overload_cast<const T &>(&T::extendBy), "intersects(box) returns true if the box intersects the given box")
.def("majorAxis",&T::majorAxis, "majorAxis() major axis of the box")
.def("isEmpty",&T::isEmpty, "isEmpty() returns true if the box is empty")
.def("isInfinite",&T::isInfinite, "isInfinite() returns true if the box covers all space")
.def("hasVolume",&T::hasVolume, "hasVolume() returns true if the box has volume");

}

template <class T, class V>
void register_box2(nanobind::module_& m, const char * name)
{
nanobind::class_<T> c(m, name);
register_box<T, V>(c);
}

template <class T, class V>
void register_box3(nanobind::module_& m, const char * name)
{
nanobind::class_<T> c(m, name);
register_box<T, V>(c);
}

void register_imath_box(nanobind::module_& m)
{
register_box2<Imath::Box2d, Imath::V2d>(m, "Box2d");
register_box2<Imath::Box2f, Imath::V2f>(m, "Box2f");

register_box3<Imath::Box3d, Imath::V3d>(m, "Box3d");
register_box3<Imath::Box3f, Imath::V3f>(m, "Box3f");

}

}
28 changes: 28 additions & 0 deletions src/nanobind/NanobindImath/NanobindImathExport.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
//
// SPDX-License-Identifier: BSD-3-Clause
// Copyright Contributors to the OpenEXR Project.
//

// clang-format off

#ifndef NANOBINDIMATHEXPORT_H
#define NANOBINDIMATHEXPORT_H

#if defined(IMATH_DLL)
#if defined(PLATFORM_VISIBILITY_AVAILABLE)
#define NANOBINDIMATH_EXPORT __attribute__((visibility("default")))
#define NANOBINDIMATH_EXPORT __attribute__((visibility("default")))
#elif defined(_MSC_VER)
#if defined(NANOBINDIMATH_BUILD)
#define NANOBINDIMATH_EXPORT __declspec(dllexport)
#else
#define NANOBINDIMATH_EXPORT __declspec(dllimport)
#endif
#else
#define NANOBINDIMATH_EXPORT
#endif
#else
#define NANOBINDIMATH_EXPORT
#endif

#endif // #ifndef NANOBINDIMATHEXPORT_H
Loading
Loading