Skip to content

Commit

Permalink
Generalize the pybind11 forward declaration of classes.
Browse files Browse the repository at this point in the history
  • Loading branch information
damienmarchal committed Oct 17, 2024
1 parent 3ebaf13 commit 2bd7ff6
Show file tree
Hide file tree
Showing 15 changed files with 101 additions and 12 deletions.
15 changes: 12 additions & 3 deletions bindings/Sofa/src/SofaPython3/Sofa/Core/Binding_Base.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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, py_shared_ptr<Base>> 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, py_shared_ptr<Base>> 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);
Expand Down
4 changes: 3 additions & 1 deletion bindings/Sofa/src/SofaPython3/Sofa/Core/Binding_Base.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
2 changes: 0 additions & 2 deletions bindings/Sofa/src/SofaPython3/Sofa/Core/Binding_BaseData.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -207,8 +207,6 @@ void moduleForwardAddBaseData(py::module& m)
void moduleAddBaseData(py::module& m)
{
/// Register the BaseData binding into the pybind11 system.
//py::class_<BaseData, std::unique_ptr<sofa::core::objectmodel::BaseData, pybind11::nodelete>> 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);
Expand Down
2 changes: 2 additions & 0 deletions bindings/Sofa/src/SofaPython3/Sofa/Core/Binding_BaseData.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
2 changes: 2 additions & 0 deletions bindings/Sofa/src/SofaPython3/Sofa/Core/Binding_BaseLink.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

#include <SofaPython3/Sofa/Core/Binding_Base.h>
#include <SofaPython3/Sofa/Core/Binding_BaseContext.h>
#include <SofaPython3/Sofa/Core/Binding_BaseMeshTopology.h>
#include <SofaPython3/PythonFactory.h>
#include <sofa/core/BaseState.h>
#include <sofa/core/objectmodel/BaseObject.h>
Expand All @@ -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_<BaseMeshTopology, Topology, py_shared_ptr<BaseMeshTopology>> basemesh(m, "BaseMeshTopology");
return basemesh;
}

void moduleForwardAddBaseMeshTopology(py::module& m)
{
getPythonClassForBaseMeshTopology(m);
}

void moduleAddBaseMeshTopology(py::module& m) {
py::class_<BaseMeshTopology, Topology, py_shared_ptr<BaseMeshTopology>> c (m, "BaseMeshTopology");
auto c = getPythonClassForBaseMeshTopology(m);

/// register the BaseMeshTopology binding in the downcasting subsystem
PythonFactory::registerType<BaseMeshTopology>([](sofa::core::objectmodel::Base* object)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
15 changes: 13 additions & 2 deletions bindings/Sofa/src/SofaPython3/Sofa/Core/Binding_BaseObject.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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_<BaseObject, Base, py_shared_ptr<BaseObject>>p(m, "Object", sofapython3::doc::baseObject::Class);
static py::class_<BaseObject, Base, py_shared_ptr<BaseObject>>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<sofa::core::objectmodel::BaseObject>(
Expand Down
2 changes: 2 additions & 0 deletions bindings/Sofa/src/SofaPython3/Sofa/Core/Binding_BaseObject.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
6 changes: 6 additions & 0 deletions bindings/Sofa/src/SofaPython3/Sofa/Core/Binding_Mass.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -94,4 +94,10 @@ void moduleAddMass(py::module &m) {
declare_mass<sofa::defaulttype::Rigid2dTypes>(m);
}

void moduleForwardAddBaseMass(py::module& m)
{
static py::class_<sofa::core::behavior::BaseMass,
sofa::core::Base, py_shared_ptr<sofa::core::behavior::BaseMass>> basemass(m, "BaseMass");
}

} // namespace sofapython3
3 changes: 3 additions & 0 deletions bindings/Sofa/src/SofaPython3/Sofa/Core/Binding_Mass.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
11 changes: 10 additions & 1 deletion bindings/Sofa/src/SofaPython3/Sofa/Core/Binding_Topology.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,17 @@ using namespace sofa::core::topology;

namespace sofapython3 {

auto getTopologyClass(py::module& m){
static py::class_<Topology, BaseObject, py_shared_ptr<Topology>> c (m, "Topology");
return c;
}

void moduleForwardAddTopology(py::module& m) {
getTopologyClass(m);
}

void moduleAddTopology(py::module& m) {
py::class_<Topology, BaseObject, py_shared_ptr<Topology>> c (m, "Topology");
getTopologyClass(m);
}

} // namespace sofapython3
3 changes: 3 additions & 0 deletions bindings/Sofa/src/SofaPython3/Sofa/Core/Binding_Topology.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
5 changes: 4 additions & 1 deletion bindings/Sofa/src/SofaPython3/Sofa/Core/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -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)
Expand Down
24 changes: 23 additions & 1 deletion bindings/Sofa/src/SofaPython3/Sofa/Core/Submodule_Core.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
using sofa::helper::logging::Message;

#include <SofaPython3/Sofa/Core/Binding_Base.h>
#include <SofaPython3/Sofa/Core/Binding_BaseClass.h>
#include <SofaPython3/Sofa/Core/Binding_BaseContext.h>
#include <SofaPython3/Sofa/Core/Binding_BaseObject.h>
#include <SofaPython3/Sofa/Core/Binding_DataDict.h>
Expand All @@ -44,6 +45,7 @@ using sofa::helper::logging::Message;
#include <SofaPython3/Sofa/Core/Binding_PythonScriptEvent.h>
#include <SofaPython3/Sofa/Core/Binding_Topology.h>
#include <SofaPython3/Sofa/Core/Binding_BaseMeshTopology.h>
#include <SofaPython3/Sofa/Core/Binding_Topology.h>
#include <SofaPython3/Sofa/Core/Binding_TaskScheduler.h>

#include <SofaPython3/Sofa/Core/Data/Binding_DataString.h>
Expand Down Expand Up @@ -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_<sofa::core::behavior::BaseMechanicalState,
Base, py_shared_ptr<sofa::core::behavior::BaseMechanicalState>> basems(core, "BaseMechanicalState");

/// When all forward declarations in pybind11 are done we can actually fully
/// define the full binding.
moduleAddPythonScriptEvent();
moduleAddDataDict(core);
moduleAddDataDictIterator(core);
Expand Down Expand Up @@ -143,7 +166,6 @@ PYBIND11_MODULE(Core, core)

msg_info("SofaPython3.Core") << "Sofa.Core unload()";
}));

}

} ///namespace sofapython3

0 comments on commit 2bd7ff6

Please sign in to comment.