/* pybind/common.h -- Basic macros Copyright (c) 2015 Wenzel Jakob All rights reserved. Use of this source code is governed by a BSD-style license that can be found in the LICENSE file. */ #pragma once #if !defined(NAMESPACE_BEGIN) #define NAMESPACE_BEGIN(name) namespace name { #endif #if !defined(NAMESPACE_END) #define NAMESPACE_END(name) } #endif #if !defined(PYTHON_EXPORT) #if defined(WIN32) || defined(_WIN32) #define PYTHON_EXPORT __declspec(dllexport) #else #define PYTHON_EXPORT __attribute__ ((visibility("default"))) #endif #endif #include #include #include #include #include #include /// Include Python header, disable linking to pythonX_d.lib on Windows in debug mode #if defined(_MSC_VER) #define HAVE_ROUND #pragma warning(push) #pragma warning(disable: 4510 4610 4512 4005) #if _DEBUG #define _DEBUG_MARKER #undef _DEBUG #endif #endif #include #include #ifdef isalnum #undef isalnum #undef isalpha #undef islower #undef isspace #undef isupper #undef tolower #undef toupper #endif #if defined(_MSC_VER) #if defined(_DEBUG_MARKER) #define _DEBUG #undef _DEBUG_MARKER #endif #pragma warning(pop) #endif #if PY_MAJOR_VERSION >= 3 #define PYTHON_PLUGIN(name) \ extern "C" PYTHON_EXPORT PyObject *PyInit_##name() #else #define PYTHON_PLUGIN(name) \ extern "C" PYTHON_EXPORT PyObject *init##name() #endif NAMESPACE_BEGIN(pybind) typedef Py_ssize_t ssize_t; /// Approach used to cast a previously unknown C++ instance into a Python object enum class return_value_policy : int { /** Automatic: copy objects returned as values and take ownership of objects returned as pointers */ automatic = 0, /** Reference the object and take ownership. Python will call the destructor and delete operator when the reference count reaches zero */ take_ownership, /** Reference the object, but do not take ownership (dangerous when C++ code deletes it and Python still has a nonzero reference count) */ reference, /** Reference the object, but do not take ownership. The object is considered be owned by the C++ instance whose method or property returned it. The Python object will increase the reference count of this 'parent' by 1 */ reference_internal, /// Create a new copy of the returned object, which will be owned by Python copy }; /// Format strings for basic number types template struct format_descriptor { }; #define PYBIND_DECL_FMT(t, n) template<> struct format_descriptor { static std::string value() { return n; }; }; PYBIND_DECL_FMT(int8_t, "b"); PYBIND_DECL_FMT(uint8_t, "B"); PYBIND_DECL_FMT(int16_t, "h"); PYBIND_DECL_FMT(uint16_t, "H"); PYBIND_DECL_FMT(int32_t, "i"); PYBIND_DECL_FMT(uint32_t, "I"); PYBIND_DECL_FMT(int64_t, "q"); PYBIND_DECL_FMT(uint64_t, "Q"); PYBIND_DECL_FMT(float, "f"); PYBIND_DECL_FMT(double, "d"); PYBIND_DECL_FMT(bool, "?"); /// Information record describing a Python buffer object struct buffer_info { void *ptr; size_t itemsize, count; std::string format; // for dense contents, this should be set to format_descriptor::value int ndim; std::vector shape; std::vector strides; buffer_info(void *ptr, size_t itemsize, const std::string &format, int ndim, const std::vector &shape, const std::vector &strides) : ptr(ptr), itemsize(itemsize), format(format), ndim(ndim), shape(shape), strides(strides) { count = 1; for (int i=0; i> struct instance { PyObject_HEAD type *value; PyObject *parent; bool owned : 1; bool constructed : 1; holder_type holder; }; /// Additional type information which does not fit into the PyTypeObjet struct type_info { PyTypeObject *type; size_t type_size; void (*init_holder)(PyObject *); std::vector implicit_conversions; buffer_info *(*get_buffer)(PyObject *, void *) = nullptr; void *get_buffer_data = nullptr; }; struct overload_hash { inline std::size_t operator()(const std::pair& v) const { size_t value = std::hash()(v.first); value ^= std::hash()(v.second) + 0x9e3779b9 + (value<<6) + (value>>2); return value; } }; /// Internal data struture used to track registered instances and types struct internals { std::unordered_map registered_types; std::unordered_map registered_instances; std::unordered_set, overload_hash> inactive_overload_cache; }; /// Return a reference to the current 'internals' information inline internals &get_internals(); /// Index sequence for convenient template metaprogramming involving tuples template struct index_sequence { }; template struct make_index_sequence : make_index_sequence { }; template struct make_index_sequence <0, S...> { typedef index_sequence type; }; /// Strip the class from a method type template struct remove_class {}; template struct remove_class { typedef R type(A...); }; template struct remove_class { typedef R type(A...); }; /// Helper template to strip away type modifiers template struct decay { typedef T type; }; template struct decay { typedef typename decay::type type; }; template struct decay { typedef typename decay::type type; }; template struct decay { typedef typename decay::type type; }; template struct decay { typedef typename decay::type type; }; template struct decay { typedef typename decay::type type; }; template struct decay { typedef typename decay::type type; }; /// Helper type to replace 'void' in some expressions struct void_type { }; /// to_string variant which also accepts strings template inline typename std::enable_if::value, std::string>::type to_string(const T &value) { return std::to_string(value); } template <> inline std::string to_string(const std::string &value) { return value; } template inline typename std::enable_if::value, std::string>::type to_string(T value) { return std::to_string((int) value); } NAMESPACE_END(detail) // C++ bindings of core Python exceptions struct stop_iteration : public std::runtime_error { public: stop_iteration(const std::string &w="") : std::runtime_error(w) {} }; struct index_error : public std::runtime_error { public: index_error(const std::string &w="") : std::runtime_error(w) {} }; struct error_already_set : public std::runtime_error { public: error_already_set() : std::runtime_error(detail::error_string()) {} }; /// Thrown when pybind::cast or handle::call fail due to a type casting error struct cast_error : public std::runtime_error { public: cast_error(const std::string &w = "") : std::runtime_error(w) {} }; NAMESPACE_END(pybind)