-
Notifications
You must be signed in to change notification settings - Fork 202
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 8fd58b5
Showing
14 changed files
with
744 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
[submodule "ext/robin_map"] | ||
path = ext/robin_map | ||
url = https://github.com/Tessil/robin-map |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
cmake_minimum_required(VERSION 3.17...3.22) | ||
project(nanobind) | ||
|
||
find_package(Python COMPONENTS Interpreter Development) | ||
|
||
add_library(nanobind-core STATIC | ||
src/module.cpp | ||
src/func.cpp | ||
) | ||
target_compile_features(nanobind-core INTERFACE cxx_std_17) | ||
set_target_properties(nanobind-core PROPERTIES | ||
CXX_VISIBILITY_PRESET hidden | ||
POSITION_INDEPENDENT_CODE ON | ||
) | ||
target_compile_features(nanobind-core PRIVATE cxx_std_17) | ||
target_include_directories(nanobind-core PRIVATE | ||
${CMAKE_CURRENT_SOURCE_DIR}/include | ||
${Python_INCLUDE_DIRS}) | ||
|
||
function(nanobind_add_module name) | ||
if (MSVC) | ||
set(NB_OPT_SIZE /Os) | ||
else() | ||
set(NB_OPT_SIZE -Os) | ||
endif() | ||
|
||
set(NB_SUFFIX ".so") | ||
set(NB_COMPILE_OPTIONS | ||
$<$<CONFIG:Release>:${NB_OPT_SIZE}> | ||
$<$<CONFIG:MinSizeRel>:${NB_OPT_SIZE}> | ||
$<$<CONFIG:RelWithDebInfo>:${NB_OPT_SIZE}>) | ||
|
||
if(MSVC) | ||
set(NB_COMPILE_OPTIONS ${NB_COMPILE_OPTIONS} /bigobj /MP) | ||
set(NB_SUFFIX ".pyd") | ||
endif() | ||
|
||
add_library(${name} MODULE ${ARGV1}) | ||
set_target_properties(${name} PROPERTIES CXX_VISIBILITY_PRESET hidden) | ||
target_compile_features(${name} PRIVATE cxx_std_17) | ||
target_compile_options(${name} PRIVATE ${NB_COMPILE_OPTIONS}) | ||
target_link_libraries(${name} nanobind-core) | ||
set_target_properties(${name} PROPERTIES PREFIX "" SUFFIX ".${Python_SOABI}${NB_SUFFIX}") | ||
target_include_directories(${name} PRIVATE | ||
${CMAKE_CURRENT_SOURCE_DIR}/include | ||
${Python_INCLUDE_DIRS}) | ||
|
||
if (APPLE) | ||
target_link_options(${name} PRIVATE -undefined dynamic_lookup) | ||
endif() | ||
endfunction() | ||
|
||
nanobind_add_module( | ||
nbtest | ||
nbtest.cpp | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
#if __cplusplus < 201703L | ||
# error NanoBind requires C++17 | ||
#endif | ||
|
||
#include <stdexcept> | ||
#include <type_traits> | ||
#include <new> | ||
|
||
#include "nb_python.h" | ||
#include "nb_defs.h" | ||
#include "nb_lib.h" | ||
#include "nb_types.h" | ||
#include "nb_attr.h" | ||
#include "nb_func.h" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
NAMESPACE_BEGIN(nanobind) | ||
|
||
struct scope { | ||
handle value; | ||
scope(handle value) : value(value) { } | ||
}; | ||
|
||
struct pred { | ||
handle value; | ||
pred(handle value) : value(value) { } | ||
}; | ||
|
||
struct name { | ||
const char *value; | ||
name(const char *value) : value(value) { } | ||
}; | ||
|
||
NAMESPACE_BEGIN(detail) | ||
|
||
inline void func_apply(void *func_rec, const pred &pred) { | ||
func_set_pred(func_rec, pred.value.ptr()); | ||
} | ||
|
||
inline void func_apply(void *func_rec, const scope &scope) { | ||
func_set_scope(func_rec, scope.value.ptr()); | ||
} | ||
|
||
inline void func_apply(void *func_rec, const name &name) { | ||
func_set_name(func_rec, name.value); | ||
} | ||
|
||
inline void func_apply(void *func_rec, const char *docstr) { | ||
func_set_docstr(func_rec, docstr); | ||
} | ||
|
||
NAMESPACE_END(detail) | ||
|
||
NAMESPACE_END(nanobind) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
#define NB_STRINGIFY(x) #x | ||
#define NB_TOSTRING(x) NB_STRINGIFY(x) | ||
#define NB_CONCAT(first, second) first##second | ||
|
||
#if !defined(NAMESPACE_BEGIN) | ||
# define NAMESPACE_BEGIN(name) namespace name { | ||
#endif | ||
|
||
#if !defined(NAMESPACE_END) | ||
# define NAMESPACE_END(name) } | ||
#endif | ||
|
||
#if !defined(NB_EXPORT) | ||
# if defined(_WIN32) | ||
# define NB_EXPORT __declspec(dllexport) | ||
# else | ||
# define NB_EXPORT __attribute__ ((visibility("default"))) | ||
# endif | ||
#endif | ||
|
||
#define NB_MODULE(name, variable) \ | ||
extern "C" [[maybe_unused]] NB_EXPORT PyObject *PyInit_##name(); \ | ||
static PyModuleDef NB_CONCAT(nanobind_module_def_, name); \ | ||
[[maybe_unused]] static void NB_CONCAT(nanobind_init_, \ | ||
name)(::nanobind::module_ &); \ | ||
extern "C" NB_EXPORT PyObject *PyInit_##name() { \ | ||
nanobind::module_ m = nanobind::reinterpret_borrow<nanobind::module_>( \ | ||
nanobind::detail::module_new( \ | ||
NB_TOSTRING(name), &NB_CONCAT(nanobind_module_def_, name))); \ | ||
try { \ | ||
NB_CONCAT(nanobind_init_, name)(m); \ | ||
return m.ptr(); \ | ||
} catch (const std::exception &e) { \ | ||
PyErr_SetString(PyExc_ImportError, e.what()); \ | ||
return nullptr; \ | ||
} \ | ||
} \ | ||
void NB_CONCAT(nanobind_init_, name)(::nanobind::module_ & (variable)) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,112 @@ | ||
NAMESPACE_BEGIN(nanobind) | ||
NAMESPACE_BEGIN(detail) | ||
|
||
template <typename Func, typename Return, typename... Args, typename... Extra> | ||
object func_create(Func &&f, Return (*)(Args...), const Extra &...extra) { | ||
struct capture { | ||
std::remove_reference_t<Func> f; | ||
}; | ||
|
||
// Store the capture object in the function record if there is space | ||
constexpr bool IsSmall = sizeof(capture) <= sizeof(void *) * 3; | ||
constexpr bool IsTrivial = std::is_trivially_destructible_v<capture>; | ||
|
||
void *func_rec = func_alloc(); | ||
void (*free_capture)(void *ptr) = nullptr; | ||
|
||
if constexpr (IsSmall) { | ||
capture *cap = std::launder((capture *) func_rec); | ||
new (cap) capture{ std::forward<Func>(f) }; | ||
|
||
if constexpr (!IsTrivial) { | ||
free_capture = [](void *func_rec_2) { | ||
capture *cap_2 = std::launder((capture *) func_rec_2); | ||
cap_2->~capture(); | ||
}; | ||
} | ||
} else { | ||
void **cap = std::launder((void **) func_rec); | ||
cap[0] = new capture{ std::forward<Func>(f) }; | ||
|
||
free_capture = [](void *func_rec_2) { | ||
void **cap_2 = std::launder((void **) func_rec_2); | ||
delete (capture *) cap_2[0]; | ||
}; | ||
} | ||
|
||
auto impl = [](void *func_rec_2) -> PyObject * { | ||
capture *cap; | ||
if constexpr (IsSmall) | ||
cap = std::launder((capture *) func_rec_2); | ||
else | ||
cap = std::launder((void **) func_rec_2)[0]; | ||
|
||
cap->f(); | ||
|
||
return nullptr; | ||
}; | ||
|
||
(detail::func_apply(func_rec, extra), ...); | ||
|
||
return reinterpret_steal<object>(func_init(func_rec, free_capture, impl)); | ||
} | ||
|
||
template <typename T> | ||
constexpr bool is_lambda_v = !std::is_function_v<T> && !std::is_pointer_v<T> && | ||
!std::is_member_pointer_v<T>; | ||
|
||
|
||
/// Strip the class from a method type | ||
template <typename T> struct remove_class { }; | ||
template <typename C, typename R, typename... A> struct remove_class<R (C::*)(A...)> { using type = R (A...); }; | ||
template <typename C, typename R, typename... A> struct remove_class<R (C::*)(A...) const> { using type = R (A...); }; | ||
|
||
NAMESPACE_END(detail) | ||
|
||
template <bool V> using enable_if_t = std::enable_if_t<V, int>; | ||
|
||
template <typename Return, typename... Args, typename... Extra> | ||
object cpp_function(Return (*f)(Args...), const Extra&... extra) { | ||
return detail::func_create(f, f, extra...); | ||
} | ||
|
||
/// Construct a cpp_function from a lambda function (possibly with internal state) | ||
template <typename Func, typename... Extra, | ||
enable_if_t<detail::is_lambda_v<std::remove_reference_t<Func>>> = 0> | ||
object cpp_function(Func &&f, const Extra &...extra) { | ||
using RawFunc = | ||
typename detail::remove_class<decltype(&Func::operator())>::type; | ||
return detail::func_create(std::forward<Func>(f), (RawFunc *) nullptr, | ||
extra...); | ||
} | ||
|
||
/// Construct a cpp_function from a class method (non-const, no ref-qualifier) | ||
template <typename Return, typename Class, typename... Args, typename... Extra> | ||
object cpp_function(Return (Class::*f)(Args...), const Extra&... extra) { | ||
return detail::func_create( | ||
[f](Class *c, Args... args) -> Return { | ||
return (c->*f)(std::forward<Args>(args)...); | ||
}, | ||
(Return(*)(Class *, Args...)) nullptr, extra...); | ||
} | ||
|
||
/// Construct a cpp_function from a class method (const, no ref-qualifier) | ||
template <typename Return, typename Class, typename... Args, typename... Extra> | ||
object cpp_function(Return (Class::*f)(Args...) const, const Extra &...extra) { | ||
return detail::func_create( | ||
[f](const Class *c, Args... args) -> Return { | ||
return (c->*f)(std::forward<Args>(args)...); | ||
}, | ||
(Return(*)(const Class *, Args...)) nullptr, extra...); | ||
} | ||
|
||
template <typename Func, typename... Extra> | ||
module_ &module_::def(const char *name_, Func &&f, const Extra &...extra) { | ||
object func = cpp_function(std::forward<Func>(f), name(name_), scope(*this), | ||
pred(getattr(*this, name_, none())), extra...); | ||
if (PyModule_AddObject(m_ptr, name_, func.release().ptr())) | ||
detail::fail("module::def(): could not add object!"); | ||
return *this; | ||
} | ||
|
||
NAMESPACE_END(nanobind) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
NAMESPACE_BEGIN(nanobind) | ||
NAMESPACE_BEGIN(detail) | ||
|
||
// ======================================================================== | ||
|
||
/// Raise a std::runtime_error with the given message | ||
#if defined(__GNUC__) | ||
__attribute__((noreturn, __format__ (__printf__, 1, 2))) | ||
#else | ||
[[noreturn]] | ||
#endif | ||
extern void raise(const char *fmt, ...); | ||
|
||
/// Abort the process with a fatal error | ||
#if defined(__GNUC__) | ||
__attribute__((noreturn, nothrow, __format__ (__printf__, 1, 2))) | ||
#else | ||
[[noreturn, noexcept]] | ||
#endif | ||
extern void fail(const char *fmt, ...); | ||
|
||
// ======================================================================== | ||
|
||
/// Create a new capsule object | ||
extern PyObject *capsule_new(const void *ptr, void (*free)(void *)) noexcept; | ||
|
||
/// Create a new extension module with the given name | ||
extern PyObject *module_new(const char *name, PyModuleDef *def) noexcept; | ||
|
||
// ======================================================================== | ||
|
||
/// Create a new handle for a function to be bound | ||
extern void *func_alloc() noexcept; | ||
|
||
/// Free all memory associated with a function handle | ||
extern void func_free(void *handle) noexcept; | ||
|
||
/// Annotate a function handle with the given flag | ||
extern void func_set_flag(void *handle, uint32_t flag) noexcept; | ||
|
||
/// Set the function name | ||
extern void func_set_name(void *handle, const char *name) noexcept; | ||
|
||
/// Set the function docstring | ||
extern void func_set_docstr(void *handle, const char *docstr) noexcept; | ||
|
||
/// Set the function scope | ||
extern void func_set_scope(void *handle, PyObject *scope) noexcept; | ||
|
||
/// Set the predecessor of a overload chain | ||
extern void func_set_pred(void *handle, PyObject *pred) noexcept; | ||
|
||
/// Create a Python function object for the given function handle | ||
extern PyObject *func_init(void *handle, void (*free_captured)(void *), | ||
PyObject *(*impl)(void *)) noexcept; | ||
|
||
NAMESPACE_END(detail) | ||
NAMESPACE_END(nanobind) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
/// Include Python header, disable linking to pythonX_d.lib on Windows in debug mode | ||
#if defined(_MSC_VER) | ||
# pragma warning(push) | ||
// C4505: 'PySlice_GetIndicesEx': unreferenced local function has been removed (PyPy only) | ||
# pragma warning(disable: 4505) | ||
# if defined(_DEBUG) && !defined(Py_DEBUG) | ||
# define PYBIND11_DEBUG_MARKER | ||
# undef _DEBUG | ||
# endif | ||
#endif | ||
|
||
#include <Python.h> | ||
#include <frameobject.h> | ||
#include <pythread.h> | ||
|
||
/* Python #defines overrides on all sorts of core functions, which | ||
tends to weak havok in C++ codebases that expect these to work | ||
like regular functions (potentially with several overloads) */ | ||
#if defined(isalnum) | ||
# undef isalnum | ||
# undef isalpha | ||
# undef islower | ||
# undef isspace | ||
# undef isupper | ||
# undef tolower | ||
# undef toupper | ||
#endif | ||
|
||
#if defined(copysign) | ||
# undef copysign | ||
#endif | ||
|
||
#if defined(_MSC_VER) | ||
# if defined(PYBIND11_DEBUG_MARKER) | ||
# define _DEBUG | ||
# undef PYBIND11_DEBUG_MARKER | ||
# endif | ||
# pragma warning(pop) | ||
#endif |
Oops, something went wrong.