-
Notifications
You must be signed in to change notification settings - Fork 100
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
Showing
21 changed files
with
1,706 additions
and
0 deletions.
There are no files selected for viewing
30 changes: 30 additions & 0 deletions
30
examples/knxPython/pybind11/.github/workflows/emscripten.yaml
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,30 @@ | ||
name: WASM | ||
|
||
on: | ||
workflow_dispatch: | ||
pull_request: | ||
branches: | ||
- master | ||
- stable | ||
- v* | ||
|
||
concurrency: | ||
group: ${{ github.workflow }}-${{ github.ref }} | ||
cancel-in-progress: true | ||
|
||
jobs: | ||
build-wasm-emscripten: | ||
name: Pyodide wheel | ||
runs-on: ubuntu-22.04 | ||
steps: | ||
- uses: actions/checkout@v4 | ||
with: | ||
submodules: true | ||
fetch-depth: 0 | ||
|
||
- uses: pypa/[email protected] | ||
env: | ||
PYODIDE_BUILD_EXPORTS: whole_archive | ||
with: | ||
package-dir: tests | ||
only: cp312-pyodide_wasm32 |
109 changes: 109 additions & 0 deletions
109
examples/knxPython/pybind11/docs/advanced/cast/functional.rst
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,109 @@ | ||
Functional | ||
########## | ||
|
||
The following features must be enabled by including :file:`pybind11/functional.h`. | ||
|
||
|
||
Callbacks and passing anonymous functions | ||
========================================= | ||
|
||
The C++11 standard brought lambda functions and the generic polymorphic | ||
function wrapper ``std::function<>`` to the C++ programming language, which | ||
enable powerful new ways of working with functions. Lambda functions come in | ||
two flavors: stateless lambda function resemble classic function pointers that | ||
link to an anonymous piece of code, while stateful lambda functions | ||
additionally depend on captured variables that are stored in an anonymous | ||
*lambda closure object*. | ||
|
||
Here is a simple example of a C++ function that takes an arbitrary function | ||
(stateful or stateless) with signature ``int -> int`` as an argument and runs | ||
it with the value 10. | ||
|
||
.. code-block:: cpp | ||
int func_arg(const std::function<int(int)> &f) { | ||
return f(10); | ||
} | ||
The example below is more involved: it takes a function of signature ``int -> int`` | ||
and returns another function of the same kind. The return value is a stateful | ||
lambda function, which stores the value ``f`` in the capture object and adds 1 to | ||
its return value upon execution. | ||
|
||
.. code-block:: cpp | ||
std::function<int(int)> func_ret(const std::function<int(int)> &f) { | ||
return [f](int i) { | ||
return f(i) + 1; | ||
}; | ||
} | ||
This example demonstrates using python named parameters in C++ callbacks which | ||
requires using ``py::cpp_function`` as a wrapper. Usage is similar to defining | ||
methods of classes: | ||
|
||
.. code-block:: cpp | ||
py::cpp_function func_cpp() { | ||
return py::cpp_function([](int i) { return i+1; }, | ||
py::arg("number")); | ||
} | ||
After including the extra header file :file:`pybind11/functional.h`, it is almost | ||
trivial to generate binding code for all of these functions. | ||
|
||
.. code-block:: cpp | ||
#include <pybind11/functional.h> | ||
PYBIND11_MODULE(example, m) { | ||
m.def("func_arg", &func_arg); | ||
m.def("func_ret", &func_ret); | ||
m.def("func_cpp", &func_cpp); | ||
} | ||
The following interactive session shows how to call them from Python. | ||
|
||
.. code-block:: pycon | ||
$ python | ||
>>> import example | ||
>>> def square(i): | ||
... return i * i | ||
... | ||
>>> example.func_arg(square) | ||
100L | ||
>>> square_plus_1 = example.func_ret(square) | ||
>>> square_plus_1(4) | ||
17L | ||
>>> plus_1 = func_cpp() | ||
>>> plus_1(number=43) | ||
44L | ||
.. warning:: | ||
|
||
Keep in mind that passing a function from C++ to Python (or vice versa) | ||
will instantiate a piece of wrapper code that translates function | ||
invocations between the two languages. Naturally, this translation | ||
increases the computational cost of each function call somewhat. A | ||
problematic situation can arise when a function is copied back and forth | ||
between Python and C++ many times in a row, in which case the underlying | ||
wrappers will accumulate correspondingly. The resulting long sequence of | ||
C++ -> Python -> C++ -> ... roundtrips can significantly decrease | ||
performance. | ||
|
||
There is one exception: pybind11 detects case where a stateless function | ||
(i.e. a function pointer or a lambda function without captured variables) | ||
is passed as an argument to another C++ function exposed in Python. In this | ||
case, there is no overhead. Pybind11 will extract the underlying C++ | ||
function pointer from the wrapped function to sidestep a potential C++ -> | ||
Python -> C++ roundtrip. This is demonstrated in :file:`tests/test_callbacks.cpp`. | ||
|
||
.. note:: | ||
|
||
This functionality is very useful when generating bindings for callbacks in | ||
C++ libraries (e.g. GUI libraries, asynchronous networking libraries, etc.). | ||
|
||
The file :file:`tests/test_callbacks.cpp` contains a complete example | ||
that demonstrates how to work with callbacks and anonymous functions in | ||
more detail. |
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,13 @@ | ||
Python C++ interface | ||
#################### | ||
|
||
pybind11 exposes Python types and functions using thin C++ wrappers, which | ||
makes it possible to conveniently call Python code from C++ without resorting | ||
to Python's C API. | ||
|
||
.. toctree:: | ||
:maxdepth: 2 | ||
|
||
object | ||
numpy | ||
utilities |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
427 changes: 427 additions & 0 deletions
427
examples/knxPython/pybind11/docs/pybind11_vs_boost_python1.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
427 changes: 427 additions & 0 deletions
427
examples/knxPython/pybind11/docs/pybind11_vs_boost_python2.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
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,2 @@ | ||
#include "detail/common.h" | ||
#warning "Including 'common.h' is deprecated. It will be removed in v3.0. Use 'pybind11.h'." |
77 changes: 77 additions & 0 deletions
77
examples/knxPython/pybind11/include/pybind11/detail/cpp_conduit.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,77 @@ | ||
// Copyright (c) 2024 The pybind Community. | ||
|
||
#pragma once | ||
|
||
#include <pybind11/pytypes.h> | ||
|
||
#include "common.h" | ||
#include "internals.h" | ||
|
||
#include <typeinfo> | ||
|
||
PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE) | ||
PYBIND11_NAMESPACE_BEGIN(detail) | ||
|
||
// Forward declaration needed here: Refactoring opportunity. | ||
extern "C" inline PyObject *pybind11_object_new(PyTypeObject *type, PyObject *, PyObject *); | ||
|
||
inline bool type_is_managed_by_our_internals(PyTypeObject *type_obj) { | ||
#if defined(PYPY_VERSION) | ||
auto &internals = get_internals(); | ||
return bool(internals.registered_types_py.find(type_obj) | ||
!= internals.registered_types_py.end()); | ||
#else | ||
return bool(type_obj->tp_new == pybind11_object_new); | ||
#endif | ||
} | ||
|
||
inline bool is_instance_method_of_type(PyTypeObject *type_obj, PyObject *attr_name) { | ||
PyObject *descr = _PyType_Lookup(type_obj, attr_name); | ||
return bool((descr != nullptr) && PyInstanceMethod_Check(descr)); | ||
} | ||
|
||
inline object try_get_cpp_conduit_method(PyObject *obj) { | ||
if (PyType_Check(obj)) { | ||
return object(); | ||
} | ||
PyTypeObject *type_obj = Py_TYPE(obj); | ||
str attr_name("_pybind11_conduit_v1_"); | ||
bool assumed_to_be_callable = false; | ||
if (type_is_managed_by_our_internals(type_obj)) { | ||
if (!is_instance_method_of_type(type_obj, attr_name.ptr())) { | ||
return object(); | ||
} | ||
assumed_to_be_callable = true; | ||
} | ||
PyObject *method = PyObject_GetAttr(obj, attr_name.ptr()); | ||
if (method == nullptr) { | ||
PyErr_Clear(); | ||
return object(); | ||
} | ||
if (!assumed_to_be_callable && PyCallable_Check(method) == 0) { | ||
Py_DECREF(method); | ||
return object(); | ||
} | ||
return reinterpret_steal<object>(method); | ||
} | ||
|
||
inline void *try_raw_pointer_ephemeral_from_cpp_conduit(handle src, | ||
const std::type_info *cpp_type_info) { | ||
object method = try_get_cpp_conduit_method(src.ptr()); | ||
if (method) { | ||
capsule cpp_type_info_capsule(const_cast<void *>(static_cast<const void *>(cpp_type_info)), | ||
typeid(std::type_info).name()); | ||
object cpp_conduit = method(bytes(PYBIND11_PLATFORM_ABI_ID), | ||
cpp_type_info_capsule, | ||
bytes("raw_pointer_ephemeral")); | ||
if (isinstance<capsule>(cpp_conduit)) { | ||
return reinterpret_borrow<capsule>(cpp_conduit).get_pointer(); | ||
} | ||
} | ||
return nullptr; | ||
} | ||
|
||
#define PYBIND11_HAS_CPP_CONDUIT 1 | ||
|
||
PYBIND11_NAMESPACE_END(detail) | ||
PYBIND11_NAMESPACE_END(PYBIND11_NAMESPACE) |
71 changes: 71 additions & 0 deletions
71
examples/knxPython/pybind11/include/pybind11/detail/exception_translation.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,71 @@ | ||
/* | ||
pybind11/detail/exception_translation.h: means to translate C++ exceptions to Python exceptions | ||
Copyright (c) 2024 The Pybind Development Team. | ||
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 | ||
|
||
#include "common.h" | ||
#include "internals.h" | ||
|
||
PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE) | ||
PYBIND11_NAMESPACE_BEGIN(detail) | ||
|
||
// Apply all the extensions translators from a list | ||
// Return true if one of the translators completed without raising an exception | ||
// itself. Return of false indicates that if there are other translators | ||
// available, they should be tried. | ||
inline bool apply_exception_translators(std::forward_list<ExceptionTranslator> &translators) { | ||
auto last_exception = std::current_exception(); | ||
|
||
for (auto &translator : translators) { | ||
try { | ||
translator(last_exception); | ||
return true; | ||
} catch (...) { | ||
last_exception = std::current_exception(); | ||
} | ||
} | ||
return false; | ||
} | ||
|
||
inline void try_translate_exceptions() { | ||
/* When an exception is caught, give each registered exception | ||
translator a chance to translate it to a Python exception. First | ||
all module-local translators will be tried in reverse order of | ||
registration. If none of the module-locale translators handle | ||
the exception (or there are no module-locale translators) then | ||
the global translators will be tried, also in reverse order of | ||
registration. | ||
A translator may choose to do one of the following: | ||
- catch the exception and call py::set_error() | ||
to set a standard (or custom) Python exception, or | ||
- do nothing and let the exception fall through to the next translator, or | ||
- delegate translation to the next translator by throwing a new type of exception. | ||
*/ | ||
|
||
bool handled = with_internals([&](internals &internals) { | ||
auto &local_exception_translators = get_local_internals().registered_exception_translators; | ||
if (detail::apply_exception_translators(local_exception_translators)) { | ||
return true; | ||
} | ||
auto &exception_translators = internals.registered_exception_translators; | ||
if (detail::apply_exception_translators(exception_translators)) { | ||
return true; | ||
} | ||
return false; | ||
}); | ||
|
||
if (!handled) { | ||
set_error(PyExc_SystemError, "Exception escaped from default exception translator!"); | ||
} | ||
} | ||
|
||
PYBIND11_NAMESPACE_END(detail) | ||
PYBIND11_NAMESPACE_END(PYBIND11_NAMESPACE) |
77 changes: 77 additions & 0 deletions
77
examples/knxPython/pybind11/include/pybind11/detail/value_and_holder.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,77 @@ | ||
// Copyright (c) 2016-2024 The Pybind Development Team. | ||
// 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 | ||
|
||
#include "common.h" | ||
|
||
#include <cstddef> | ||
#include <typeinfo> | ||
|
||
PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE) | ||
PYBIND11_NAMESPACE_BEGIN(detail) | ||
|
||
struct value_and_holder { | ||
instance *inst = nullptr; | ||
size_t index = 0u; | ||
const detail::type_info *type = nullptr; | ||
void **vh = nullptr; | ||
|
||
// Main constructor for a found value/holder: | ||
value_and_holder(instance *i, const detail::type_info *type, size_t vpos, size_t index) | ||
: inst{i}, index{index}, type{type}, | ||
vh{inst->simple_layout ? inst->simple_value_holder | ||
: &inst->nonsimple.values_and_holders[vpos]} {} | ||
|
||
// Default constructor (used to signal a value-and-holder not found by get_value_and_holder()) | ||
value_and_holder() = default; | ||
|
||
// Used for past-the-end iterator | ||
explicit value_and_holder(size_t index) : index{index} {} | ||
|
||
template <typename V = void> | ||
V *&value_ptr() const { | ||
return reinterpret_cast<V *&>(vh[0]); | ||
} | ||
// True if this `value_and_holder` has a non-null value pointer | ||
explicit operator bool() const { return value_ptr() != nullptr; } | ||
|
||
template <typename H> | ||
H &holder() const { | ||
return reinterpret_cast<H &>(vh[1]); | ||
} | ||
bool holder_constructed() const { | ||
return inst->simple_layout | ||
? inst->simple_holder_constructed | ||
: (inst->nonsimple.status[index] & instance::status_holder_constructed) != 0u; | ||
} | ||
// NOLINTNEXTLINE(readability-make-member-function-const) | ||
void set_holder_constructed(bool v = true) { | ||
if (inst->simple_layout) { | ||
inst->simple_holder_constructed = v; | ||
} else if (v) { | ||
inst->nonsimple.status[index] |= instance::status_holder_constructed; | ||
} else { | ||
inst->nonsimple.status[index] &= (std::uint8_t) ~instance::status_holder_constructed; | ||
} | ||
} | ||
bool instance_registered() const { | ||
return inst->simple_layout | ||
? inst->simple_instance_registered | ||
: ((inst->nonsimple.status[index] & instance::status_instance_registered) != 0); | ||
} | ||
// NOLINTNEXTLINE(readability-make-member-function-const) | ||
void set_instance_registered(bool v = true) { | ||
if (inst->simple_layout) { | ||
inst->simple_instance_registered = v; | ||
} else if (v) { | ||
inst->nonsimple.status[index] |= instance::status_instance_registered; | ||
} else { | ||
inst->nonsimple.status[index] &= (std::uint8_t) ~instance::status_instance_registered; | ||
} | ||
} | ||
}; | ||
|
||
PYBIND11_NAMESPACE_END(detail) | ||
PYBIND11_NAMESPACE_END(PYBIND11_NAMESPACE) |
Oops, something went wrong.