diff --git a/Plugin/CMakeLists.txt b/Plugin/CMakeLists.txt
index f53e987a..b2b1aabc 100644
--- a/Plugin/CMakeLists.txt
+++ b/Plugin/CMakeLists.txt
@@ -4,6 +4,7 @@ set(HEADER_FILES
${CMAKE_CURRENT_SOURCE_DIR}/src/SofaPython3/config.h.in
${CMAKE_CURRENT_SOURCE_DIR}/src/SofaPython3/initModule.h
${CMAKE_CURRENT_SOURCE_DIR}/src/SofaPython3/PythonEnvironment.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/src/SofaPython3/PyBindHelper.h
${CMAKE_CURRENT_SOURCE_DIR}/src/SofaPython3/SceneLoaderPY3.h
${CMAKE_CURRENT_SOURCE_DIR}/src/SofaPython3/SpellingSuggestionHelper.h
diff --git a/Plugin/src/SofaPython3/PyBindHelper.h b/Plugin/src/SofaPython3/PyBindHelper.h
new file mode 100644
index 00000000..e8a5787b
--- /dev/null
+++ b/Plugin/src/SofaPython3/PyBindHelper.h
@@ -0,0 +1,190 @@
+/******************************************************************************
+* SofaPython3 plugin *
+* (c) 2021 CNRS, University of Lille, INRIA *
+* *
+* This program is free software; you can redistribute it and/or modify it *
+* under the terms of the GNU Lesser General Public License as published by *
+* the Free Software Foundation; either version 2.1 of the License, or (at *
+* your option) any later version. *
+* *
+* This program is distributed in the hope that it will be useful, but WITHOUT *
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
+* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License *
+* for more details. *
+* *
+* You should have received a copy of the GNU Lesser General Public License *
+* along with this program. If not, see . *
+*******************************************************************************
+* Contact information: contact@sofa-framework.org *
+******************************************************************************/
+#pragma once
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+namespace sofapython3
+{
+
+class PythonMethodDescription
+{
+public:
+ void add_entry(const std::string& signature="")
+ {
+ signatures.push_back(signature);
+ docstrings.push_back("");
+ }
+
+ /// Parse the docstring generated by pybind11 to extract the different method signatures
+ /// and for each the associated docstring.
+ void parse_docstring(const std::string& name, std::string docstring)
+ {
+ std::smatch m;
+ std::string last;
+ std::regex e;
+
+ if(signatures.size()==0)
+ return;
+
+ // easy path. Take the signature, then consider the remaining as a docstring
+ if(signatures.size()==1)
+ {
+ e = std::regex("("+name+".*)");
+ if (std::regex_search (docstring, m,e))
+ {
+ for (auto x:m)
+ last = x;
+ if(signatures[0].size()==0)
+ signatures[0] = last;
+ docstrings[0] = m.suffix().str();
+ }
+ return;
+ }
+
+ int idx = 0;
+ e = std::regex("(1\\. )("+name+".*)");
+ while (std::regex_search (docstring, m,e))
+ {
+ for (auto x:m)
+ last = x;
+
+ if(signatures[idx].size()==0)
+ signatures[idx] = last;
+
+ if(idx>0)
+ docstrings[idx-1] = m.prefix().str();
+ idx++;
+ docstring = m.suffix().str();
+
+ auto pex = "("+std::to_string(idx+1)+"\\. )("+name+".*)";
+ e = std::regex(pex);
+ }
+ if(!docstring.empty())
+ docstrings[idx-1] = docstring;
+ }
+
+ /// Generates the docstring from the extracted ones from pybind11 and applying the
+ /// customs signatures, if any.
+ const std::string build_docstring(const std::string& name) const
+ {
+ std::stringstream tmp;
+ if(signatures.size() == 1)
+ {
+ tmp << signatures[0];
+ tmp << docstrings[0];
+ return tmp.str();
+ }
+ else
+ {
+ tmp << name <<"(*args, **kwargs)\n";
+ tmp << "Overloaded function.\n\n";
+ }
+ for(unsigned int i=0;i signatures; //< signatures for the method overrides
+ std::vector docstrings; //< docstrings for the method overrides
+
+};
+
+template
+class def_method
+{
+public:
+ def_method(Class classI, const std::string& name_) :
+ classInstance(classI), name(name_)
+ {
+ }
+
+ virtual ~def_method()
+ {
+ description.parse_docstring(name, get_current_docstring());
+ set_docstring(description.build_docstring(name));
+ }
+
+ template
+ def_method& add_override(Args ... args)
+ {
+ classInstance.def(name.c_str(), args...);
+ description.add_entry();
+ return *this;
+ }
+
+ template
+ def_method& add_override(const char* signature, Args ... args)
+ {
+ classInstance.def(name.c_str(), args...);
+ description.add_entry(signature);
+ return *this;
+ }
+
+ std::string get_current_docstring() const {
+ std::string tmp;
+ // get the raw python object out of the classInstance
+ auto method = classInstance.attr(name.c_str()).ptr();
+ // if it is an instance method get the raw CFunction
+ if(Py_TYPE(method) == &PyInstanceMethod_Type){
+ method = ((PyInstanceMethodObject*)(method))->func;
+ }
+ // if it is a CFunction, get its docstring
+ if(Py_TYPE(method) == &PyCFunction_Type){
+ auto cmethod = (PyCFunctionObject*)method;
+ tmp = std::string(cmethod->m_ml->ml_doc);
+ }
+ return tmp;
+ }
+
+ void set_docstring(const std::string& docstring) const
+ {
+ // get the raw python object out of the classInstance
+ auto method = classInstance.attr(name.c_str()).ptr();
+ // if it is an instance method get the raw CFunction
+ if(Py_TYPE(method) == &PyInstanceMethod_Type){
+ method = ((PyInstanceMethodObject*)(method))->func;
+ }
+ // if it is a CFunction, get its docstring
+ if(Py_TYPE(method) == &PyCFunction_Type){
+ auto cmethod = (PyCFunctionObject*)method;
+ cmethod->m_ml->ml_doc = strdup(docstring.c_str());
+ }else
+ {
+ msg_error("SofaPython3") << "Unable to build docstring for method " << name;
+ }
+ }
+
+private:
+ Class classInstance; //< stores the pybind::class_
+ std::string name; //< stores the name of the method we declares
+ PythonMethodDescription description;
+};
+
+}
diff --git a/bindings/Sofa/src/SofaPython3/Sofa/Core/Binding_Base.cpp b/bindings/Sofa/src/SofaPython3/Sofa/Core/Binding_Base.cpp
index 6aa8d763..81365ecf 100644
--- a/bindings/Sofa/src/SofaPython3/Sofa/Core/Binding_Base.cpp
+++ b/bindings/Sofa/src/SofaPython3/Sofa/Core/Binding_Base.cpp
@@ -449,12 +449,21 @@ py::object BindingBase::setDataValues(Base& self, py::kwargs kwargs)
return py::none();
}
+auto getBaseBinding(py::module& m)
+{
+ static py::class_> base(m, "Base", py::dynamic_attr(), doc::base::BaseClass);
+ return base;
+}
+
+void moduleForwardAddBase(py::module& m)
+{
+ getBaseBinding(m);
+}
+
void moduleAddBase(py::module &m)
{
- moduleForwardAddBaseData(m);
- moduleForwardAddBaseLink(m);
+ auto base = getBaseBinding(m);
- py::class_> base(m, "Base", py::dynamic_attr(), doc::base::BaseClass);
/// set & get the name as string. The alternative is to access the data field using
/// obj.name.value = "aName"
base.def("getName", [](Base& b){ return b.getName(); }, sofapython3::doc::base::getName);
diff --git a/bindings/Sofa/src/SofaPython3/Sofa/Core/Binding_Base.h b/bindings/Sofa/src/SofaPython3/Sofa/Core/Binding_Base.h
index 670ce54b..06a98e59 100644
--- a/bindings/Sofa/src/SofaPython3/Sofa/Core/Binding_Base.h
+++ b/bindings/Sofa/src/SofaPython3/Sofa/Core/Binding_Base.h
@@ -68,7 +68,9 @@ class BindingBase
static std::string getLinkPath(sofa::core::objectmodel::Base& self);
};
-
+/// Forward declaration in pybind11.
+/// more details in: https://github.com/sofa-framework/SofaPython3/pull/457
+void moduleForwardAddBase(pybind11::module& m);
void moduleAddBase(pybind11::module& m);
} /// namespace sofapython3
diff --git a/bindings/Sofa/src/SofaPython3/Sofa/Core/Binding_BaseClass.cpp b/bindings/Sofa/src/SofaPython3/Sofa/Core/Binding_BaseClass.cpp
new file mode 100644
index 00000000..7fbbc0dd
--- /dev/null
+++ b/bindings/Sofa/src/SofaPython3/Sofa/Core/Binding_BaseClass.cpp
@@ -0,0 +1,48 @@
+/******************************************************************************
+* SOFA, Simulation Open-Framework Architecture *
+* (c) 2021 INRIA, USTL, UJF, CNRS, MGH *
+* *
+* This program is free software; you can redistribute it and/or modify it *
+* under the terms of the GNU Lesser General Public License as published by *
+* the Free Software Foundation; either version 2.1 of the License, or (at *
+* your option) any later version. *
+* *
+* This program is distributed in the hope that it will be useful, but WITHOUT *
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
+* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License *
+* for more details. *
+* *
+* You should have received a copy of the GNU Lesser General Public License *
+* along with this program. If not, see . *
+*******************************************************************************
+* Contact information: contact@sofa-framework.org *
+******************************************************************************/
+
+#include
+#include
+#include
+
+namespace sofapython3
+{
+using namespace sofa::core::objectmodel;
+
+/// Makes an alias for the pybind11 namespace to increase readability.
+namespace py { using namespace pybind11; }
+
+auto getBaseClassBinding(py::module& m)
+{
+ static py::class_> base(m, "BaseClass", doc::baseclass::classdocstring);
+ return base;
+}
+
+void moduleForwardAddBaseClass(py::module& m)
+{
+ getBaseClassBinding(m);
+}
+
+void moduleAddBaseClass(py::module &m)
+{
+ // adds here the BaseClass's binded function (if any).
+}
+
+} /// namespace sofapython3
diff --git a/bindings/Sofa/src/SofaPython3/Sofa/Core/Binding_BaseClass.h b/bindings/Sofa/src/SofaPython3/Sofa/Core/Binding_BaseClass.h
new file mode 100644
index 00000000..6ae2c6b7
--- /dev/null
+++ b/bindings/Sofa/src/SofaPython3/Sofa/Core/Binding_BaseClass.h
@@ -0,0 +1,32 @@
+/******************************************************************************
+* SOFA, Simulation Open-Framework Architecture *
+* (c) 2021 INRIA, USTL, UJF, CNRS, MGH *
+* *
+* This program is free software; you can redistribute it and/or modify it *
+* under the terms of the GNU Lesser General Public License as published by *
+* the Free Software Foundation; either version 2.1 of the License, or (at *
+* your option) any later version. *
+* *
+* This program is distributed in the hope that it will be useful, but WITHOUT *
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
+* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License *
+* for more details. *
+* *
+* You should have received a copy of the GNU Lesser General Public License *
+* along with this program. If not, see . *
+*******************************************************************************
+* Contact information: contact@sofa-framework.org *
+******************************************************************************/
+
+#pragma once
+
+#include
+
+namespace sofapython3 {
+
+/// Forward declaration in pybind11.
+/// more details in: https://github.com/sofa-framework/SofaPython3/pull/457
+void moduleForwardAddBaseClass(pybind11::module& m);
+void moduleAddBaseClass(pybind11::module& m);
+
+} /// namespace sofapython3
diff --git a/bindings/Sofa/src/SofaPython3/Sofa/Core/Binding_BaseClass_doc.h b/bindings/Sofa/src/SofaPython3/Sofa/Core/Binding_BaseClass_doc.h
new file mode 100644
index 00000000..2ed3d7d3
--- /dev/null
+++ b/bindings/Sofa/src/SofaPython3/Sofa/Core/Binding_BaseClass_doc.h
@@ -0,0 +1,31 @@
+/******************************************************************************
+* SOFA, Simulation Open-Framework Architecture *
+* (c) 2021 INRIA, USTL, UJF, CNRS, MGH *
+* *
+* This program is free software; you can redistribute it and/or modify it *
+* under the terms of the GNU Lesser General Public License as published by *
+* the Free Software Foundation; either version 2.1 of the License, or (at *
+* your option) any later version. *
+* *
+* This program is distributed in the hope that it will be useful, but WITHOUT *
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
+* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License *
+* for more details. *
+* *
+* You should have received a copy of the GNU Lesser General Public License *
+* along with this program. If not, see . *
+*******************************************************************************
+* Contact information: contact@sofa-framework.org *
+******************************************************************************/
+
+#pragma once
+
+namespace sofapython3::doc::baseclass {
+
+static auto classdocstring =
+ R"(Class hierarchy reflection base class
+This class provides information on the class and parent classes of components.
+It is created by using the SOFA_CLASS macro on each new class declaration.
+All classes deriving from Base should use the SOFA_CLASS macro within their declaration.)";
+
+}
diff --git a/bindings/Sofa/src/SofaPython3/Sofa/Core/Binding_BaseData.cpp b/bindings/Sofa/src/SofaPython3/Sofa/Core/Binding_BaseData.cpp
index ecc83750..d00341e6 100644
--- a/bindings/Sofa/src/SofaPython3/Sofa/Core/Binding_BaseData.cpp
+++ b/bindings/Sofa/src/SofaPython3/Sofa/Core/Binding_BaseData.cpp
@@ -207,8 +207,6 @@ void moduleForwardAddBaseData(py::module& m)
void moduleAddBaseData(py::module& m)
{
/// Register the BaseData binding into the pybind11 system.
- //py::class_> data(m, "Data", sofapython3::doc::baseData::BaseDataClass);
-
auto data =getPythonClassForBaseData(m);
data.def("getName", [](BaseData& b){ return b.getName(); }, sofapython3::doc::baseData::getName);
data.def("setName", [](BaseData& b, const std::string& s){ b.setName(s); }, sofapython3::doc::baseData::setName);
diff --git a/bindings/Sofa/src/SofaPython3/Sofa/Core/Binding_BaseData.h b/bindings/Sofa/src/SofaPython3/Sofa/Core/Binding_BaseData.h
index badd6522..54be7010 100644
--- a/bindings/Sofa/src/SofaPython3/Sofa/Core/Binding_BaseData.h
+++ b/bindings/Sofa/src/SofaPython3/Sofa/Core/Binding_BaseData.h
@@ -24,6 +24,8 @@
namespace sofapython3 {
+ /// Forward declaration in pybind11.
+ /// more details in: https://github.com/sofa-framework/SofaPython3/pull/457
void moduleForwardAddBaseData(pybind11::module& m);
void moduleAddBaseData(pybind11::module& m);
diff --git a/bindings/Sofa/src/SofaPython3/Sofa/Core/Binding_BaseLink.h b/bindings/Sofa/src/SofaPython3/Sofa/Core/Binding_BaseLink.h
index 1cf5df4a..7beca2fa 100644
--- a/bindings/Sofa/src/SofaPython3/Sofa/Core/Binding_BaseLink.h
+++ b/bindings/Sofa/src/SofaPython3/Sofa/Core/Binding_BaseLink.h
@@ -24,6 +24,8 @@
namespace sofapython3 {
+ /// Forward declaration in pybind11.
+ /// more details in: https://github.com/sofa-framework/SofaPython3/pull/457
void moduleForwardAddBaseLink(pybind11::module& m);
void moduleAddBaseLink(pybind11::module& m);
diff --git a/bindings/Sofa/src/SofaPython3/Sofa/Core/Binding_BaseMeshTopology.cpp b/bindings/Sofa/src/SofaPython3/Sofa/Core/Binding_BaseMeshTopology.cpp
index 2759c530..886179b0 100644
--- a/bindings/Sofa/src/SofaPython3/Sofa/Core/Binding_BaseMeshTopology.cpp
+++ b/bindings/Sofa/src/SofaPython3/Sofa/Core/Binding_BaseMeshTopology.cpp
@@ -21,6 +21,7 @@
#include
#include
+#include
#include
#include
#include
@@ -36,8 +37,21 @@ using namespace sofa::core::topology;
namespace sofapython3 {
+
+auto getPythonClassForBaseMeshTopology(py::module& m)
+{
+ /// Register the BaseData binding into the pybind11 system.
+ static py::class_> basemesh(m, "BaseMeshTopology");
+ return basemesh;
+}
+
+void moduleForwardAddBaseMeshTopology(py::module& m)
+{
+ getPythonClassForBaseMeshTopology(m);
+}
+
void moduleAddBaseMeshTopology(py::module& m) {
- py::class_> c (m, "BaseMeshTopology");
+ auto c = getPythonClassForBaseMeshTopology(m);
/// register the BaseMeshTopology binding in the downcasting subsystem
PythonFactory::registerType([](sofa::core::objectmodel::Base* object)
diff --git a/bindings/Sofa/src/SofaPython3/Sofa/Core/Binding_BaseMeshTopology.h b/bindings/Sofa/src/SofaPython3/Sofa/Core/Binding_BaseMeshTopology.h
index db28451e..7f8dd115 100644
--- a/bindings/Sofa/src/SofaPython3/Sofa/Core/Binding_BaseMeshTopology.h
+++ b/bindings/Sofa/src/SofaPython3/Sofa/Core/Binding_BaseMeshTopology.h
@@ -24,6 +24,9 @@
namespace sofapython3 {
+/// Forward declaration in pybind11.
+/// more details in: https://github.com/sofa-framework/SofaPython3/pull/457
+void moduleForwardAddBaseMeshTopology(pybind11::module &m);
void moduleAddBaseMeshTopology(pybind11::module &m);
} // namespace sofapython3
diff --git a/bindings/Sofa/src/SofaPython3/Sofa/Core/Binding_BaseObject.cpp b/bindings/Sofa/src/SofaPython3/Sofa/Core/Binding_BaseObject.cpp
index 7f9a476c..06fe77b6 100644
--- a/bindings/Sofa/src/SofaPython3/Sofa/Core/Binding_BaseObject.cpp
+++ b/bindings/Sofa/src/SofaPython3/Sofa/Core/Binding_BaseObject.cpp
@@ -188,10 +188,21 @@ py::object __getitem__(BaseObject &self, std::string s)
return getItem(self, s);
}
-void moduleAddBaseObject(py::module& m)
+auto getBaseObjectBinding(py::module& m)
{
/// Register the BaseObject binding into the pybind11 typing system
- py::class_>p(m, "Object", sofapython3::doc::baseObject::Class);
+ static py::class_>p(m, "Object", sofapython3::doc::baseObject::Class);
+ return p;
+}
+
+void moduleForwardAddBaseObject(py::module& m)
+{
+ getBaseObjectBinding(m);
+}
+
+void moduleAddBaseObject(py::module& m)
+{
+ auto p = getBaseObjectBinding(m);
/// Register the BaseObject binding into the downcasting subsystem
PythonFactory::registerType(
diff --git a/bindings/Sofa/src/SofaPython3/Sofa/Core/Binding_BaseObject.h b/bindings/Sofa/src/SofaPython3/Sofa/Core/Binding_BaseObject.h
index 3e40176d..b85eed1f 100644
--- a/bindings/Sofa/src/SofaPython3/Sofa/Core/Binding_BaseObject.h
+++ b/bindings/Sofa/src/SofaPython3/Sofa/Core/Binding_BaseObject.h
@@ -29,6 +29,8 @@ class BaseObject;
namespace sofapython3 {
pybind11::object getItem(const sofa::core::objectmodel::BaseObject & self, const std::string& path);
+
+void moduleForwardAddBaseObject(pybind11::module &m);
void moduleAddBaseObject(pybind11::module &m);
} /// namespace sofapython
diff --git a/bindings/Sofa/src/SofaPython3/Sofa/Core/Binding_Mass.cpp b/bindings/Sofa/src/SofaPython3/Sofa/Core/Binding_Mass.cpp
index 75af4211..268b7a0d 100644
--- a/bindings/Sofa/src/SofaPython3/Sofa/Core/Binding_Mass.cpp
+++ b/bindings/Sofa/src/SofaPython3/Sofa/Core/Binding_Mass.cpp
@@ -94,4 +94,10 @@ void moduleAddMass(py::module &m) {
declare_mass(m);
}
+void moduleForwardAddBaseMass(py::module& m)
+{
+ static py::class_> basemass(m, "BaseMass");
+}
+
} // namespace sofapython3
diff --git a/bindings/Sofa/src/SofaPython3/Sofa/Core/Binding_Mass.h b/bindings/Sofa/src/SofaPython3/Sofa/Core/Binding_Mass.h
index 826b78da..7316b6ab 100644
--- a/bindings/Sofa/src/SofaPython3/Sofa/Core/Binding_Mass.h
+++ b/bindings/Sofa/src/SofaPython3/Sofa/Core/Binding_Mass.h
@@ -24,6 +24,9 @@
namespace sofapython3 {
+/// Forward declaration in pybind11.
+/// more details in: https://github.com/sofa-framework/SofaPython3/pull/457
+void moduleForwardAddBaseMass(pybind11::module &m);
void moduleAddMass(pybind11::module &m);
} /// namespace sofapython3
diff --git a/bindings/Sofa/src/SofaPython3/Sofa/Core/Binding_Node.cpp b/bindings/Sofa/src/SofaPython3/Sofa/Core/Binding_Node.cpp
index dda992d1..f20275db 100644
--- a/bindings/Sofa/src/SofaPython3/Sofa/Core/Binding_Node.cpp
+++ b/bindings/Sofa/src/SofaPython3/Sofa/Core/Binding_Node.cpp
@@ -61,6 +61,7 @@ using sofapython3::PythonEnvironment;
#include
#include
+#include
using sofa::core::objectmodel::BaseObjectDescription;
@@ -294,6 +295,12 @@ py::object addObjectKwargs(Node* self, const std::string& type, const py::kwargs
return PythonFactory::toPython(object.get());
}
+py::object addObjectGenericType(Node* self, const py::type type, const py::kwargs& kwargs)
+{
+ auto name = py::cast(type.attr("__name__"));
+ return addObjectKwargs(self, name, kwargs);
+}
+
/// Implement the addObject function.
py::object addKwargs(Node* self, const py::object& callable, const py::kwargs& kwargs)
{
@@ -605,61 +612,69 @@ void sendEvent(Node* self, py::object pyUserData, char* eventName)
sofapython3::PythonScriptEvent event(self, eventName, pyUserData);
self->propagateEvent(sofa::core::execparams::defaultInstance(), &event);
}
-
}
void moduleAddNode(py::module &m) {
- /// Register the complete parent-child relationship between Base and Node to the pybind11
- /// typing system.
- py::class_>(m, "BaseNode");
-
- py::class_>
- p(m, "Node", sofapython3::doc::sofa::core::Node::Class);
-
- PythonFactory::registerType(
- [](sofa::core::objectmodel::Base* object)
{
- return py::cast(dynamic_cast(object->toBaseNode()));
- });
-
- p.def(py::init(&__init__noname), sofapython3::doc::sofa::core::Node::init);
- p.def(py::init(&__init__), sofapython3::doc::sofa::core::Node::init1Arg, py::arg("name"));
- p.def("init", &init, sofapython3::doc::sofa::core::Node::initSofa );
- p.def("add", &addKwargs, sofapython3::doc::sofa::core::Node::addKwargs);
- p.def("addObject", &addObjectKwargs, sofapython3::doc::sofa::core::Node::addObjectKwargs);
- p.def("addObject", &addObject, sofapython3::doc::sofa::core::Node::addObject, py::keep_alive<0, 2>());
- p.def("createObject", &createObject, sofapython3::doc::sofa::core::Node::createObject, py::keep_alive<0, 2>());
- p.def("hasObject", &hasObject, sofapython3::doc::sofa::core::Node::hasObject);
- p.def("getObject", &getObject, sofapython3::doc::sofa::core::Node::getObject);
- p.def("addChild", &addChildKwargs, sofapython3::doc::sofa::core::Node::addChildKwargs);
- p.def("addChild", &addChild, sofapython3::doc::sofa::core::Node::addChild, py::keep_alive<0, 2>());
- p.def("createChild", &createChild, sofapython3::doc::sofa::core::Node::createChild, py::keep_alive<0, 2>());
- p.def("getChild", &getChild, sofapython3::doc::sofa::core::Node::getChild);
- p.def("removeChild", &removeChild, sofapython3::doc::sofa::core::Node::removeChild);
- p.def("removeChild", &removeChildByName, sofapython3::doc::sofa::core::Node::removeChildWithName);
- p.def("getRoot", &getRoot, sofapython3::doc::sofa::core::Node::getRoot);
- p.def("getPathName", &Node::getPathName, sofapython3::doc::sofa::core::Node::getPathName);
- p.def("getLinkPath", &getLinkPath, sofapython3::doc::sofa::core::Node::getLinkPath);
- p.def_property_readonly("children", &property_children, sofapython3::doc::sofa::core::Node::children);
- p.def_property_readonly("parents", &property_parents, sofapython3::doc::sofa::core::Node::parents);
- p.def_property_readonly("objects", &property_objects, sofapython3::doc::sofa::core::Node::objects);
- p.def("__getattr__", &__getattr__);
- p.def("__getitem__", &__getitem__);
- p.def("removeObject", &removeObject, sofapython3::doc::sofa::core::Node::removeObject);
- p.def("getRootPath", &Node::getRootPath, sofapython3::doc::sofa::core::Node::getRootPath);
- p.def("moveChild", &moveChild, sofapython3::doc::sofa::core::Node::moveChild);
- p.def("isInitialized", &Node::isInitialized, sofapython3::doc::sofa::core::Node::isInitialized);
- p.def("getAsACreateObjectParameter", &getLinkPath, sofapython3::doc::sofa::core::Node::getAsACreateObjectParameter);
- p.def("detachFromGraph", &Node::detachFromGraph, sofapython3::doc::sofa::core::Node::detachFromGraph);
- p.def("getMass", &getMass, sofapython3::doc::sofa::core::Node::getMass);
- p.def("hasODESolver", &hasODESolver, sofapython3::doc::sofa::core::Node::hasODESolver);
- p.def("getForceField", &getForceField, sofapython3::doc::sofa::core::Node::getForceField);
- p.def("getMechanicalState", &getMechanicalState, sofapython3::doc::sofa::core::Node::getMechanicalState);
- p.def("getMechanicalMapping", &getMechanicalMapping, sofapython3::doc::sofa::core::Node::getMechanicalMapping);
- p.def("sendEvent", &sendEvent, sofapython3::doc::sofa::core::Node::sendEvent);
+ /// Register the complete parent-child relationship between Base and Node to the pybind11
+ /// typing system.
+ py::class_>(m, "BaseNode");
+
+ py::class_>
+ p(m, "Node", sofapython3::doc::sofa::core::Node::Class);
+
+ PythonFactory::registerType(
+ [](sofa::core::objectmodel::Base* object)
+ {
+ return py::cast(dynamic_cast(object->toBaseNode()));
+ });
+
+ p.def(py::init(&__init__noname), sofapython3::doc::sofa::core::Node::init);
+ p.def(py::init(&__init__), sofapython3::doc::sofa::core::Node::init1Arg, py::arg("name"));
+ p.def("init", &init, sofapython3::doc::sofa::core::Node::initSofa );
+ p.def("add", &addKwargs, sofapython3::doc::sofa::core::Node::addKwargs);
+
+ def_method(p, "addObject")
+ .add_override("addObject(self, typename: str, **kwargs) -> Sofa.Core.Object",
+ addObjectKwargs, sofapython3::doc::sofa::core::Node::addObjectKwargs)
+ .add_override(addObject,
+ sofapython3::doc::sofa::core::Node::addObject, py::keep_alive<0, 2>())
+ .add_override("addObject[T](self, python_type: type, **kwargs) -> T",
+ addObjectGenericType, sofapython3::doc::sofa::core::Node::addObjectGenerictype);
+
+ p.def("createObject", &createObject, sofapython3::doc::sofa::core::Node::createObject, py::keep_alive<0, 2>());
+ p.def("hasObject", &hasObject, sofapython3::doc::sofa::core::Node::hasObject);
+ p.def("getObject", &getObject, sofapython3::doc::sofa::core::Node::getObject);
+ p.def("addChild", &addChildKwargs, sofapython3::doc::sofa::core::Node::addChildKwargs);
+ p.def("addChild", &addChild, sofapython3::doc::sofa::core::Node::addChild, py::keep_alive<0, 2>());
+ p.def("createChild", &createChild, sofapython3::doc::sofa::core::Node::createChild, py::keep_alive<0, 2>());
+ p.def("getChild", &getChild, sofapython3::doc::sofa::core::Node::getChild);
+ p.def("removeChild", &removeChild, sofapython3::doc::sofa::core::Node::removeChild);
+ p.def("removeChild", &removeChildByName, sofapython3::doc::sofa::core::Node::removeChildWithName);
+ p.def("getRoot", &getRoot, sofapython3::doc::sofa::core::Node::getRoot);
+ p.def("getPathName", &Node::getPathName, sofapython3::doc::sofa::core::Node::getPathName);
+ p.def("getLinkPath", &getLinkPath, sofapython3::doc::sofa::core::Node::getLinkPath);
+ p.def_property_readonly("children", &property_children, sofapython3::doc::sofa::core::Node::children);
+ p.def_property_readonly("parents", &property_parents, sofapython3::doc::sofa::core::Node::parents);
+ p.def_property_readonly("objects", &property_objects, sofapython3::doc::sofa::core::Node::objects);
+ p.def("__getattr__", &__getattr__);
+ p.def("__getitem__", &__getitem__);
+ p.def("removeObject", &removeObject, sofapython3::doc::sofa::core::Node::removeObject);
+ p.def("getRootPath", &Node::getRootPath, sofapython3::doc::sofa::core::Node::getRootPath);
+ p.def("moveChild", &moveChild, sofapython3::doc::sofa::core::Node::moveChild);
+ p.def("isInitialized", &Node::isInitialized, sofapython3::doc::sofa::core::Node::isInitialized);
+ p.def("getAsACreateObjectParameter", &getLinkPath, sofapython3::doc::sofa::core::Node::getAsACreateObjectParameter);
+ p.def("detachFromGraph", &Node::detachFromGraph, sofapython3::doc::sofa::core::Node::detachFromGraph);
+ p.def("getMass", &getMass, sofapython3::doc::sofa::core::Node::getMass);
+ p.def("hasODESolver", &hasODESolver, sofapython3::doc::sofa::core::Node::hasODESolver);
+ p.def("getForceField", &getForceField, sofapython3::doc::sofa::core::Node::getForceField);
+ p.def("getMechanicalState", &getMechanicalState, sofapython3::doc::sofa::core::Node::getMechanicalState);
+ p.def("getMechanicalMapping", &getMechanicalMapping, sofapython3::doc::sofa::core::Node::getMechanicalMapping);
+ p.def("sendEvent", &sendEvent, sofapython3::doc::sofa::core::Node::sendEvent);
+ }
}
} /// namespace sofapython3
diff --git a/bindings/Sofa/src/SofaPython3/Sofa/Core/Binding_Node.h b/bindings/Sofa/src/SofaPython3/Sofa/Core/Binding_Node.h
index 9224ab1d..608eadbe 100644
--- a/bindings/Sofa/src/SofaPython3/Sofa/Core/Binding_Node.h
+++ b/bindings/Sofa/src/SofaPython3/Sofa/Core/Binding_Node.h
@@ -23,6 +23,7 @@
namespace sofapython3 {
+void moduleForwardAddNode(pybind11::module& m);
void moduleAddNode(pybind11::module &m);
} /// namespace sofapython3
diff --git a/bindings/Sofa/src/SofaPython3/Sofa/Core/Binding_Node_doc.h b/bindings/Sofa/src/SofaPython3/Sofa/Core/Binding_Node_doc.h
index 3f971926..1aa62f97 100644
--- a/bindings/Sofa/src/SofaPython3/Sofa/Core/Binding_Node_doc.h
+++ b/bindings/Sofa/src/SofaPython3/Sofa/Core/Binding_Node_doc.h
@@ -84,8 +84,8 @@ static auto Class =
# fast access.
n["child1.child2.dofs.position"]
-
)";
+
static auto init =
R"(
Initialize the components of this node and all the nodes which depend on it.
@@ -123,27 +123,30 @@ static auto addKwargs =
node.add(Cube, name="MyCube"")
)";
-
static auto addObjectKwargs =
R"(
- Add an object.
+ Creates and add a new sofa object to the node.
Detect the implemented interfaces and add the object to the corresponding lists.
:param self: the node itself
- :param type: type of the object
- :param kwargs
- :type self: Sofa.Simulation.Node*
- :type type: string&
- :type kwargs: kwargs&
+ :param typename: name of the type of the object to create
+ :param kwargs: extra parameteres to initialize the created object.
+ )";
+
+static auto addObjectGenerictype =
+ R"(
+ Creates and add a new sofa object to the node.
+ :param self: the node itself
+ :param type: the component's type to add, type's name is used as sofa factory's type name
+ :return: the created component
)";
static auto addObject =
R"(
- Add an object.
+ Adds an existing object to the node.
Detect the implemented interfaces and add the object to the corresponding lists.
:param self: the node itself
- :param object: the object to be added
- :type self: Sofa.Simulation.Node&
- :type object: Sofa.Simulation.BaseObject*
+ :param object: the component to add
+ :return: the added component
)";
static auto createObject =
diff --git a/bindings/Sofa/src/SofaPython3/Sofa/Core/Binding_Topology.cpp b/bindings/Sofa/src/SofaPython3/Sofa/Core/Binding_Topology.cpp
index ed57ba11..63c182c5 100644
--- a/bindings/Sofa/src/SofaPython3/Sofa/Core/Binding_Topology.cpp
+++ b/bindings/Sofa/src/SofaPython3/Sofa/Core/Binding_Topology.cpp
@@ -35,8 +35,17 @@ using namespace sofa::core::topology;
namespace sofapython3 {
+auto getTopologyClass(py::module& m){
+ static py::class_> c (m, "Topology");
+ return c;
+}
+
+void moduleForwardAddTopology(py::module& m) {
+ getTopologyClass(m);
+}
+
void moduleAddTopology(py::module& m) {
- py::class_> c (m, "Topology");
+ getTopologyClass(m);
}
} // namespace sofapython3
diff --git a/bindings/Sofa/src/SofaPython3/Sofa/Core/Binding_Topology.h b/bindings/Sofa/src/SofaPython3/Sofa/Core/Binding_Topology.h
index 5f89f0e1..4bd7d4d1 100644
--- a/bindings/Sofa/src/SofaPython3/Sofa/Core/Binding_Topology.h
+++ b/bindings/Sofa/src/SofaPython3/Sofa/Core/Binding_Topology.h
@@ -24,6 +24,9 @@
namespace sofapython3 {
+/// Forward declaration in pybind11.
+/// more details in: https://github.com/sofa-framework/SofaPython3/pull/457
+void moduleForwardAddTopology(pybind11::module &m);
void moduleAddTopology(pybind11::module &m);
} // namespace sofapython3
diff --git a/bindings/Sofa/src/SofaPython3/Sofa/Core/CMakeLists.txt b/bindings/Sofa/src/SofaPython3/Sofa/Core/CMakeLists.txt
index 6dad5fea..d7ff4fd7 100644
--- a/bindings/Sofa/src/SofaPython3/Sofa/Core/CMakeLists.txt
+++ b/bindings/Sofa/src/SofaPython3/Sofa/Core/CMakeLists.txt
@@ -3,6 +3,8 @@ project(Bindings.Sofa.Core)
set(HEADER_FILES
${CMAKE_CURRENT_SOURCE_DIR}/Binding_Base.h
${CMAKE_CURRENT_SOURCE_DIR}/Binding_Base_doc.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/Binding_BaseClass.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/Binding_BaseClass_doc.h
${CMAKE_CURRENT_SOURCE_DIR}/Binding_DataDict.h
${CMAKE_CURRENT_SOURCE_DIR}/Binding_DataDict_doc.h
${CMAKE_CURRENT_SOURCE_DIR}/Binding_BaseData.h
@@ -51,6 +53,7 @@ set(HEADER_FILES
set(SOURCE_FILES
${CMAKE_CURRENT_SOURCE_DIR}/Binding_Base.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/Binding_BaseClass.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Binding_BaseData.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Binding_DataDict.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Binding_BaseObject.cpp
@@ -72,12 +75,12 @@ set(SOURCE_FILES
${CMAKE_CURRENT_SOURCE_DIR}/Binding_NodeIterator.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Binding_PointSetTopologyModifier.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Binding_Prefab.cpp
- ${CMAKE_CURRENT_SOURCE_DIR}/Submodule_Core.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Binding_PythonScriptEvent.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Binding_BaseLink.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Binding_Topology.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Binding_BaseMeshTopology.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Binding_TaskScheduler.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/Submodule_Core.cpp
)
if (NOT TARGET SofaPython3::Plugin)
diff --git a/bindings/Sofa/src/SofaPython3/Sofa/Core/Submodule_Core.cpp b/bindings/Sofa/src/SofaPython3/Sofa/Core/Submodule_Core.cpp
index 546bb435..462d220c 100644
--- a/bindings/Sofa/src/SofaPython3/Sofa/Core/Submodule_Core.cpp
+++ b/bindings/Sofa/src/SofaPython3/Sofa/Core/Submodule_Core.cpp
@@ -23,6 +23,7 @@
using sofa::helper::logging::Message;
#include
+#include
#include
#include
#include
@@ -44,6 +45,7 @@ using sofa::helper::logging::Message;
#include
#include
#include
+#include
#include
#include
@@ -103,6 +105,27 @@ PYBIND11_MODULE(Core, core)
#Sofa.Core.WriteAccessor
)doc";
+
+
+ /// Forward declaration of a class in pybind11.
+ /// The general idea is that to avoid typeing errors in pybind11 because of -yet- to
+ /// define classes it is needed to register binded class before any use (including use
+ /// in function signature inferance)
+ /// more details in: https://github.com/sofa-framework/SofaPython3/pull/457
+ moduleForwardAddBaseClass(core);
+ moduleForwardAddBase(core);
+ moduleForwardAddBaseObject(core);
+ moduleForwardAddBaseData(core);
+ moduleForwardAddBaseLink(core);
+ moduleForwardAddTopology(core);
+ moduleForwardAddBaseMeshTopology(core);
+ moduleForwardAddBaseMass(core);
+
+ py::class_> basems(core, "BaseMechanicalState");
+
+ /// When all forward declarations in pybind11 are done we can actually fully
+ /// define the full binding.
moduleAddPythonScriptEvent();
moduleAddDataDict(core);
moduleAddDataDictIterator(core);
@@ -143,7 +166,6 @@ PYBIND11_MODULE(Core, core)
msg_info("SofaPython3.Core") << "Sofa.Core unload()";
}));
-
}
} ///namespace sofapython3