mirror of
https://github.com/pybind/pybind11.git
synced 2024-11-24 14:15:11 +00:00
Replace PYBIND11_PLUGIN with PYBIND11_MODULE
This commit also adds `doc()` to `object_api` as a shortcut for the `attr("__doc__")` accessor. The module macro changes from: ```c++ PYBIND11_PLUGIN(example) { pybind11::module m("example", "pybind11 example plugin"); m.def("add", [](int a, int b) { return a + b; }); return m.ptr(); } ``` to: ```c++ PYBIND11_MODULE(example, m) { m.doc() = "pybind11 example plugin"; m.def("add", [](int a, int b) { return a + b; }); } ``` Using the old macro results in a deprecation warning. The warning actually points to the `pybind11_init` function (since attributes don't bind to macros), but the message should be quite clear: "PYBIND11_PLUGIN is deprecated, use PYBIND11_MODULE".
This commit is contained in:
parent
b700c5d672
commit
443ab5946b
@ -56,14 +56,10 @@ trivial to generate binding code for all of these functions.
|
||||
|
||||
#include <pybind11/functional.h>
|
||||
|
||||
PYBIND11_PLUGIN(example) {
|
||||
py::module m("example", "pybind11 example plugin");
|
||||
|
||||
PYBIND11_MODULE(example, m) {
|
||||
m.def("func_arg", &func_arg);
|
||||
m.def("func_ret", &func_ret);
|
||||
m.def("func_cpp", &func_cpp);
|
||||
|
||||
return m.ptr();
|
||||
}
|
||||
|
||||
The following interactive session shows how to call them from Python.
|
||||
|
@ -45,9 +45,7 @@ Normally, the binding code for these classes would look as follows:
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
PYBIND11_PLUGIN(example) {
|
||||
py::module m("example", "pybind11 example plugin");
|
||||
|
||||
PYBIND11_MODULE(example, m) {
|
||||
py::class_<Animal> animal(m, "Animal");
|
||||
animal
|
||||
.def("go", &Animal::go);
|
||||
@ -56,8 +54,6 @@ Normally, the binding code for these classes would look as follows:
|
||||
.def(py::init<>());
|
||||
|
||||
m.def("call_go", &call_go);
|
||||
|
||||
return m.ptr();
|
||||
}
|
||||
|
||||
However, these bindings are impossible to extend: ``Animal`` is not
|
||||
@ -97,11 +93,9 @@ function have different names, e.g. ``operator()`` vs ``__call__``.
|
||||
The binding code also needs a few minor adaptations (highlighted):
|
||||
|
||||
.. code-block:: cpp
|
||||
:emphasize-lines: 4,6,7
|
||||
|
||||
PYBIND11_PLUGIN(example) {
|
||||
py::module m("example", "pybind11 example plugin");
|
||||
:emphasize-lines: 2,4,5
|
||||
|
||||
PYBIND11_MODULE(example, m) {
|
||||
py::class_<Animal, PyAnimal /* <--- trampoline*/> animal(m, "Animal");
|
||||
animal
|
||||
.def(py::init<>())
|
||||
@ -111,8 +105,6 @@ The binding code also needs a few minor adaptations (highlighted):
|
||||
.def(py::init<>());
|
||||
|
||||
m.def("call_go", &call_go);
|
||||
|
||||
return m.ptr();
|
||||
}
|
||||
|
||||
Importantly, pybind11 is made aware of the trampoline helper class by
|
||||
@ -491,9 +483,7 @@ to Python.
|
||||
|
||||
#include <pybind11/operators.h>
|
||||
|
||||
PYBIND11_PLUGIN(example) {
|
||||
py::module m("example", "pybind11 example plugin");
|
||||
|
||||
PYBIND11_MODULE(example, m) {
|
||||
py::class_<Vector2>(m, "Vector2")
|
||||
.def(py::init<float, float>())
|
||||
.def(py::self + py::self)
|
||||
@ -502,8 +492,6 @@ to Python.
|
||||
.def(float() * py::self)
|
||||
.def(py::self * float())
|
||||
.def("__repr__", &Vector2::toString);
|
||||
|
||||
return m.ptr();
|
||||
}
|
||||
|
||||
Note that a line like
|
||||
|
@ -28,7 +28,7 @@ multiple Python threads. Taking :ref:`overriding_virtuals` as an example, this
|
||||
could be realized as follows (important changes highlighted):
|
||||
|
||||
.. code-block:: cpp
|
||||
:emphasize-lines: 8,9,33,34
|
||||
:emphasize-lines: 8,9,31,32
|
||||
|
||||
class PyAnimal : public Animal {
|
||||
public:
|
||||
@ -49,9 +49,7 @@ could be realized as follows (important changes highlighted):
|
||||
}
|
||||
};
|
||||
|
||||
PYBIND11_PLUGIN(example) {
|
||||
py::module m("example", "pybind11 example plugin");
|
||||
|
||||
PYBIND11_MODULE(example, m) {
|
||||
py::class_<Animal, PyAnimal> animal(m, "Animal");
|
||||
animal
|
||||
.def(py::init<>())
|
||||
@ -65,8 +63,6 @@ could be realized as follows (important changes highlighted):
|
||||
py::gil_scoped_release release;
|
||||
return call_go(animal);
|
||||
});
|
||||
|
||||
return m.ptr();
|
||||
}
|
||||
|
||||
The ``call_go`` wrapper can also be simplified using the `call_guard` policy
|
||||
@ -233,15 +229,11 @@ The class ``options`` allows you to selectively suppress auto-generated signatur
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
PYBIND11_PLUGIN(example) {
|
||||
py::module m("example", "pybind11 example plugin");
|
||||
|
||||
PYBIND11_MODULE(example, m) {
|
||||
py::options options;
|
||||
options.disable_function_signatures();
|
||||
|
||||
|
||||
m.def("add", [](int a, int b) { return a + b; }, "A function which adds two numbers");
|
||||
|
||||
return m.ptr();
|
||||
}
|
||||
|
||||
Note that changes to the settings affect only function bindings created during the
|
||||
|
@ -190,7 +190,7 @@ expects the type followed by field names:
|
||||
};
|
||||
|
||||
// ...
|
||||
PYBIND11_PLUGIN(test) {
|
||||
PYBIND11_MODULE(test, m) {
|
||||
// ...
|
||||
|
||||
PYBIND11_NUMPY_DTYPE(A, x, y);
|
||||
@ -284,10 +284,8 @@ simply using ``vectorize``).
|
||||
return result;
|
||||
}
|
||||
|
||||
PYBIND11_PLUGIN(test) {
|
||||
py::module m("test");
|
||||
PYBIND11_MODULE(test, m) {
|
||||
m.def("add_arrays", &add_arrays, "Add two NumPy arrays");
|
||||
return m.ptr();
|
||||
}
|
||||
|
||||
.. seealso::
|
||||
|
@ -63,16 +63,12 @@ code?
|
||||
std::shared_ptr<Child> child;
|
||||
};
|
||||
|
||||
PYBIND11_PLUGIN(example) {
|
||||
py::module m("example");
|
||||
|
||||
PYBIND11_MODULE(example, m) {
|
||||
py::class_<Child, std::shared_ptr<Child>>(m, "Child");
|
||||
|
||||
py::class_<Parent, std::shared_ptr<Parent>>(m, "Parent")
|
||||
.def(py::init<>())
|
||||
.def("get_child", &Parent::get_child);
|
||||
|
||||
return m.ptr();
|
||||
}
|
||||
|
||||
The following Python code will cause undefined behavior (and likely a
|
||||
|
@ -96,25 +96,21 @@ a file named :file:`example.cpp` with the following contents:
|
||||
return i + j;
|
||||
}
|
||||
|
||||
namespace py = pybind11;
|
||||
|
||||
PYBIND11_PLUGIN(example) {
|
||||
py::module m("example", "pybind11 example plugin");
|
||||
PYBIND11_MODULE(example, m) {
|
||||
m.doc() = "pybind11 example plugin"; // optional module docstring
|
||||
|
||||
m.def("add", &add, "A function which adds two numbers");
|
||||
|
||||
return m.ptr();
|
||||
}
|
||||
|
||||
.. [#f1] In practice, implementation and binding code will generally be located
|
||||
in separate files.
|
||||
|
||||
The :func:`PYBIND11_PLUGIN` macro creates a function that will be called when an
|
||||
``import`` statement is issued from within Python. The next line creates a
|
||||
module named ``example`` (with the supplied docstring). The method
|
||||
:func:`module::def` generates binding code that exposes the
|
||||
``add()`` function to Python. The last line returns the internal Python object
|
||||
associated with ``m`` to the Python interpreter.
|
||||
The :func:`PYBIND11_MODULE` macro creates a function that will be called when an
|
||||
``import`` statement is issued from within Python. The module name (``example``)
|
||||
is given as the fist macro argument (it should not be in quotes). The second
|
||||
argument (``m``) defines a variable of type :class:`py::module <module>` which
|
||||
is the main interface for creating bindings. The method :func:`module::def`
|
||||
generates binding code that exposes the ``add()`` function to Python.
|
||||
|
||||
.. note::
|
||||
|
||||
@ -261,12 +257,10 @@ converted using the function ``py::cast``.
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
PYBIND11_PLUGIN(example) {
|
||||
py::module m("example", "pybind11 example plugin");
|
||||
PYBIND11_MODULE(example, m) {
|
||||
m.attr("the_answer") = 42;
|
||||
py::object world = py::cast("World");
|
||||
m.attr("what") = world;
|
||||
return m.ptr();
|
||||
}
|
||||
|
||||
These are then accessible from Python:
|
||||
|
@ -33,10 +33,8 @@ def generate_dummy_code_pybind11(nclasses=10):
|
||||
result = "#include <pybind11/pybind11.h>\n\n"
|
||||
result += "namespace py = pybind11;\n\n"
|
||||
result += decl + '\n'
|
||||
result += "PYBIND11_PLUGIN(example) {\n"
|
||||
result += " py::module m(\"example\");"
|
||||
result += "PYBIND11_MODULE(example, m) {\n"
|
||||
result += bindings
|
||||
result += " return m.ptr();"
|
||||
result += "}"
|
||||
return result
|
||||
|
||||
|
@ -31,8 +31,7 @@ Here is an example of the binding code for one class:
|
||||
};
|
||||
...
|
||||
|
||||
PYBIND11_PLUGIN(example) {
|
||||
py::module m("example");
|
||||
PYBIND11_MODULE(example, m) {
|
||||
...
|
||||
py::class_<cl034>(m, "cl034")
|
||||
.def("fn_000", &cl034::fn_000)
|
||||
@ -40,7 +39,6 @@ Here is an example of the binding code for one class:
|
||||
.def("fn_002", &cl034::fn_002)
|
||||
.def("fn_003", &cl034::fn_003)
|
||||
...
|
||||
return m.ptr();
|
||||
}
|
||||
|
||||
The Boost.Python version looks almost identical except that a return value
|
||||
|
@ -27,15 +27,11 @@ The binding code for ``Pet`` looks as follows:
|
||||
|
||||
namespace py = pybind11;
|
||||
|
||||
PYBIND11_PLUGIN(example) {
|
||||
py::module m("example", "pybind11 example plugin");
|
||||
|
||||
PYBIND11_MODULE(example, m) {
|
||||
py::class_<Pet>(m, "Pet")
|
||||
.def(py::init<const std::string &>())
|
||||
.def("setName", &Pet::setName)
|
||||
.def("getName", &Pet::getName);
|
||||
|
||||
return m.ptr();
|
||||
}
|
||||
|
||||
:class:`class_` creates bindings for a C++ *class* or *struct*-style data
|
||||
|
24
docs/faq.rst
24
docs/faq.rst
@ -4,30 +4,24 @@ Frequently asked questions
|
||||
"ImportError: dynamic module does not define init function"
|
||||
===========================================================
|
||||
|
||||
1. Make sure that the name specified in ``pybind::module`` and
|
||||
``PYBIND11_PLUGIN`` is consistent and identical to the filename of the
|
||||
extension library. The latter should not contain any extra prefixes (e.g.
|
||||
``test.so`` instead of ``libtest.so``).
|
||||
|
||||
2. If the above did not fix your issue, then you are likely using an
|
||||
incompatible version of Python (for instance, the extension library was
|
||||
compiled against Python 2, while the interpreter is running on top of some
|
||||
version of Python 3, or vice versa)
|
||||
You are likely using an incompatible version of Python (for instance, the
|
||||
extension library was compiled against Python 2, while the interpreter is
|
||||
running on top of some version of Python 3, or vice versa).
|
||||
|
||||
"Symbol not found: ``__Py_ZeroStruct`` / ``_PyInstanceMethod_Type``"
|
||||
========================================================================
|
||||
|
||||
See item 2 of the first answer.
|
||||
See the first answer.
|
||||
|
||||
"SystemError: dynamic module not initialized properly"
|
||||
======================================================
|
||||
|
||||
See item 2 of the first answer.
|
||||
See the first answer.
|
||||
|
||||
The Python interpreter immediately crashes when importing my module
|
||||
===================================================================
|
||||
|
||||
See item 2 of the first answer.
|
||||
See the first answer.
|
||||
|
||||
CMake doesn't detect the right Python version
|
||||
=============================================
|
||||
@ -104,14 +98,10 @@ following example:
|
||||
void init_ex2(py::module &);
|
||||
/* ... */
|
||||
|
||||
PYBIND11_PLUGIN(example) {
|
||||
py::module m("example", "pybind example plugin");
|
||||
|
||||
PYBIND11_MODULE(example, m) {
|
||||
init_ex1(m);
|
||||
init_ex2(m);
|
||||
/* ... */
|
||||
|
||||
return m.ptr();
|
||||
}
|
||||
|
||||
:file:`ex1.cpp`:
|
||||
|
@ -12,7 +12,7 @@ Reference
|
||||
Macros
|
||||
======
|
||||
|
||||
.. doxygendefine:: PYBIND11_PLUGIN
|
||||
.. doxygendefine:: PYBIND11_MODULE
|
||||
|
||||
.. _core_types:
|
||||
|
||||
|
@ -194,6 +194,8 @@ extern "C" {
|
||||
PYBIND11_TOSTRING(PYBIND11_VERSION_MAJOR) "_" PYBIND11_TOSTRING(PYBIND11_VERSION_MINOR) "__"
|
||||
|
||||
/** \rst
|
||||
***Deprecated in favor of PYBIND11_MODULE***
|
||||
|
||||
This macro creates the entry point that will be invoked when the Python interpreter
|
||||
imports a plugin library. Please create a `module` in the function body and return
|
||||
the pointer to its underlying Python object at the end.
|
||||
@ -207,6 +209,7 @@ extern "C" {
|
||||
}
|
||||
\endrst */
|
||||
#define PYBIND11_PLUGIN(name) \
|
||||
PYBIND11_DEPRECATED("PYBIND11_PLUGIN is deprecated, use PYBIND11_MODULE") \
|
||||
static PyObject *pybind11_init(); \
|
||||
PYBIND11_PLUGIN_IMPL(name) { \
|
||||
int major, minor; \
|
||||
@ -234,6 +237,54 @@ extern "C" {
|
||||
} \
|
||||
PyObject *pybind11_init()
|
||||
|
||||
/** \rst
|
||||
This macro creates the entry point that will be invoked when the Python interpreter
|
||||
imports an extension module. The module name is given as the fist argument and it
|
||||
should not be in quotes. The second macro argument defines a variable of type
|
||||
`py::module` which can be used to initialize the module.
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
PYBIND11_MODULE(example, m) {
|
||||
m.doc() = "pybind11 example module";
|
||||
|
||||
// Add bindings here
|
||||
m.def("foo", []() {
|
||||
return "Hello, World!";
|
||||
});
|
||||
}
|
||||
\endrst */
|
||||
#define PYBIND11_MODULE(name, variable) \
|
||||
static void pybind11_init_##name(pybind11::module &); \
|
||||
PYBIND11_PLUGIN_IMPL(name) { \
|
||||
int major, minor; \
|
||||
if (sscanf(Py_GetVersion(), "%i.%i", &major, &minor) != 2) { \
|
||||
PyErr_SetString(PyExc_ImportError, "Can't parse Python version."); \
|
||||
return nullptr; \
|
||||
} else if (major != PY_MAJOR_VERSION || minor != PY_MINOR_VERSION) { \
|
||||
PyErr_Format(PyExc_ImportError, \
|
||||
"Python version mismatch: module was compiled for " \
|
||||
"version %i.%i, while the interpreter is running " \
|
||||
"version %i.%i.", PY_MAJOR_VERSION, PY_MINOR_VERSION, \
|
||||
major, minor); \
|
||||
return nullptr; \
|
||||
} \
|
||||
auto m = pybind11::module(#name); \
|
||||
try { \
|
||||
pybind11_init_##name(m); \
|
||||
return m.ptr(); \
|
||||
} catch (pybind11::error_already_set &e) { \
|
||||
e.clear(); \
|
||||
PyErr_SetString(PyExc_ImportError, e.what()); \
|
||||
return nullptr; \
|
||||
} catch (const std::exception &e) { \
|
||||
PyErr_SetString(PyExc_ImportError, e.what()); \
|
||||
return nullptr; \
|
||||
} \
|
||||
} \
|
||||
void pybind11_init_##name(pybind11::module &variable)
|
||||
|
||||
|
||||
NAMESPACE_BEGIN(pybind11)
|
||||
|
||||
using ssize_t = Py_ssize_t;
|
||||
|
@ -117,6 +117,9 @@ public:
|
||||
PYBIND11_DEPRECATED("Use py::str(obj) instead")
|
||||
pybind11::str str() const;
|
||||
|
||||
/// Get or set the object's docstring, i.e. ``obj.__doc__``.
|
||||
str_attr_accessor doc() const;
|
||||
|
||||
/// Return the object's current reference count
|
||||
int ref_count() const { return static_cast<int>(Py_REFCNT(derived().ptr())); }
|
||||
/// Return a handle to the Python type object underlying the instance
|
||||
@ -1248,6 +1251,9 @@ template <typename D> template <typename T> bool object_api<D>::contains(T &&ite
|
||||
template <typename D>
|
||||
pybind11::str object_api<D>::str() const { return pybind11::str(derived()); }
|
||||
|
||||
template <typename D>
|
||||
str_attr_accessor object_api<D>::doc() const { return attr("__doc__"); }
|
||||
|
||||
template <typename D>
|
||||
handle object_api<D>::get_type() const { return (PyObject *) Py_TYPE(derived().ptr()); }
|
||||
|
||||
|
@ -52,8 +52,8 @@ void bind_ConstructorStats(py::module &m) {
|
||||
;
|
||||
}
|
||||
|
||||
PYBIND11_PLUGIN(pybind11_tests) {
|
||||
py::module m("pybind11_tests", "pybind testing plugin");
|
||||
PYBIND11_MODULE(pybind11_tests, m) {
|
||||
m.doc() = "pybind11 test module";
|
||||
|
||||
bind_ConstructorStats(m);
|
||||
|
||||
@ -61,6 +61,4 @@ PYBIND11_PLUGIN(pybind11_tests) {
|
||||
initializer(m);
|
||||
|
||||
if (!py::hasattr(m, "have_eigen")) m.attr("have_eigen") = false;
|
||||
|
||||
return m.ptr();
|
||||
}
|
||||
|
@ -1,10 +1,6 @@
|
||||
#include <pybind11/pybind11.h>
|
||||
namespace py = pybind11;
|
||||
|
||||
PYBIND11_PLUGIN(test_cmake_build) {
|
||||
py::module m("test_cmake_build");
|
||||
|
||||
PYBIND11_MODULE(test_cmake_build, m) {
|
||||
m.def("add", [](int i, int j) { return i + j; });
|
||||
|
||||
return m.ptr();
|
||||
}
|
||||
|
@ -59,4 +59,5 @@ def test_pydoc():
|
||||
import pybind11_tests
|
||||
import pydoc
|
||||
|
||||
assert pybind11_tests.__doc__ == "pybind11 test module"
|
||||
assert pydoc.text.docmodule(pybind11_tests)
|
||||
|
Loading…
Reference in New Issue
Block a user