Skip to content

Commit cb4e6bf

Browse files
[fork] Fix type forward declaration in the bindings (#477)
* Example on how to fix pybind11 type forward declaration so stubgens knows about them. The problem: Depending on the definition order of the binded classes, there may have incorrect types if Base is useing BaseData... but BaseData is only binded after Base. The PR propose a solution for that using a decidcated "forward" registration patter. * Add binding for BaseClass It should be completed if ones want more feature than just class declaration * Generalize the pybind11 forward declaration of classes. --------- Co-authored-by: Damien Marchal <[email protected]>
1 parent 6376097 commit cb4e6bf

18 files changed

+212
-12
lines changed

bindings/Sofa/src/SofaPython3/Sofa/Core/Binding_Base.cpp

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -449,12 +449,21 @@ py::object BindingBase::setDataValues(Base& self, py::kwargs kwargs)
449449
return py::none();
450450
}
451451

452+
auto getBaseBinding(py::module& m)
453+
{
454+
static py::class_<Base, py_shared_ptr<Base>> base(m, "Base", py::dynamic_attr(), doc::base::BaseClass);
455+
return base;
456+
}
457+
458+
void moduleForwardAddBase(py::module& m)
459+
{
460+
getBaseBinding(m);
461+
}
462+
452463
void moduleAddBase(py::module &m)
453464
{
454-
moduleForwardAddBaseData(m);
455-
moduleForwardAddBaseLink(m);
465+
auto base = getBaseBinding(m);
456466

457-
py::class_<Base, py_shared_ptr<Base>> base(m, "Base", py::dynamic_attr(), doc::base::BaseClass);
458467
/// set & get the name as string. The alternative is to access the data field using
459468
/// obj.name.value = "aName"
460469
base.def("getName", [](Base& b){ return b.getName(); }, sofapython3::doc::base::getName);

bindings/Sofa/src/SofaPython3/Sofa/Core/Binding_Base.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,9 @@ class BindingBase
6868
static std::string getLinkPath(sofa::core::objectmodel::Base& self);
6969
};
7070

71-
71+
/// Forward declaration in pybind11.
72+
/// more details in: https://github.com/sofa-framework/SofaPython3/pull/457
73+
void moduleForwardAddBase(pybind11::module& m);
7274
void moduleAddBase(pybind11::module& m);
7375

7476
} /// namespace sofapython3
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
/******************************************************************************
2+
* SOFA, Simulation Open-Framework Architecture *
3+
* (c) 2021 INRIA, USTL, UJF, CNRS, MGH *
4+
* *
5+
* This program is free software; you can redistribute it and/or modify it *
6+
* under the terms of the GNU Lesser General Public License as published by *
7+
* the Free Software Foundation; either version 2.1 of the License, or (at *
8+
* your option) any later version. *
9+
* *
10+
* This program is distributed in the hope that it will be useful, but WITHOUT *
11+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
12+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License *
13+
* for more details. *
14+
* *
15+
* You should have received a copy of the GNU Lesser General Public License *
16+
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
17+
*******************************************************************************
18+
* Contact information: [email protected] *
19+
******************************************************************************/
20+
21+
#include <SofaPython3/Sofa/Core/Binding_BaseClass.h>
22+
#include <SofaPython3/Sofa/Core/Binding_BaseClass_doc.h>
23+
#include <sofa/core/objectmodel/BaseClass.h>
24+
25+
namespace sofapython3
26+
{
27+
using namespace sofa::core::objectmodel;
28+
29+
/// Makes an alias for the pybind11 namespace to increase readability.
30+
namespace py { using namespace pybind11; }
31+
32+
auto getBaseClassBinding(py::module& m)
33+
{
34+
static py::class_<BaseClass, std::unique_ptr<BaseClass, py::nodelete>> base(m, "BaseClass", doc::baseclass::classdocstring);
35+
return base;
36+
}
37+
38+
void moduleForwardAddBaseClass(py::module& m)
39+
{
40+
getBaseClassBinding(m);
41+
}
42+
43+
void moduleAddBaseClass(py::module &m)
44+
{
45+
// adds here the BaseClass's binded function (if any).
46+
}
47+
48+
} /// namespace sofapython3
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
/******************************************************************************
2+
* SOFA, Simulation Open-Framework Architecture *
3+
* (c) 2021 INRIA, USTL, UJF, CNRS, MGH *
4+
* *
5+
* This program is free software; you can redistribute it and/or modify it *
6+
* under the terms of the GNU Lesser General Public License as published by *
7+
* the Free Software Foundation; either version 2.1 of the License, or (at *
8+
* your option) any later version. *
9+
* *
10+
* This program is distributed in the hope that it will be useful, but WITHOUT *
11+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
12+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License *
13+
* for more details. *
14+
* *
15+
* You should have received a copy of the GNU Lesser General Public License *
16+
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
17+
*******************************************************************************
18+
* Contact information: [email protected] *
19+
******************************************************************************/
20+
21+
#pragma once
22+
23+
#include <pybind11/pybind11.h>
24+
25+
namespace sofapython3 {
26+
27+
/// Forward declaration in pybind11.
28+
/// more details in: https://github.com/sofa-framework/SofaPython3/pull/457
29+
void moduleForwardAddBaseClass(pybind11::module& m);
30+
void moduleAddBaseClass(pybind11::module& m);
31+
32+
} /// namespace sofapython3
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
/******************************************************************************
2+
* SOFA, Simulation Open-Framework Architecture *
3+
* (c) 2021 INRIA, USTL, UJF, CNRS, MGH *
4+
* *
5+
* This program is free software; you can redistribute it and/or modify it *
6+
* under the terms of the GNU Lesser General Public License as published by *
7+
* the Free Software Foundation; either version 2.1 of the License, or (at *
8+
* your option) any later version. *
9+
* *
10+
* This program is distributed in the hope that it will be useful, but WITHOUT *
11+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
12+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License *
13+
* for more details. *
14+
* *
15+
* You should have received a copy of the GNU Lesser General Public License *
16+
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
17+
*******************************************************************************
18+
* Contact information: [email protected] *
19+
******************************************************************************/
20+
21+
#pragma once
22+
23+
namespace sofapython3::doc::baseclass {
24+
25+
static auto classdocstring =
26+
R"(Class hierarchy reflection base class
27+
This class provides information on the class and parent classes of components.
28+
It is created by using the SOFA_CLASS macro on each new class declaration.
29+
All classes deriving from Base should use the SOFA_CLASS macro within their declaration.)";
30+
31+
}

bindings/Sofa/src/SofaPython3/Sofa/Core/Binding_BaseData.cpp

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -207,8 +207,6 @@ void moduleForwardAddBaseData(py::module& m)
207207
void moduleAddBaseData(py::module& m)
208208
{
209209
/// Register the BaseData binding into the pybind11 system.
210-
//py::class_<BaseData, std::unique_ptr<sofa::core::objectmodel::BaseData, pybind11::nodelete>> data(m, "Data", sofapython3::doc::baseData::BaseDataClass);
211-
212210
auto data =getPythonClassForBaseData(m);
213211
data.def("getName", [](BaseData& b){ return b.getName(); }, sofapython3::doc::baseData::getName);
214212
data.def("setName", [](BaseData& b, const std::string& s){ b.setName(s); }, sofapython3::doc::baseData::setName);

bindings/Sofa/src/SofaPython3/Sofa/Core/Binding_BaseData.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@
2424

2525
namespace sofapython3 {
2626

27+
/// Forward declaration in pybind11.
28+
/// more details in: https://github.com/sofa-framework/SofaPython3/pull/457
2729
void moduleForwardAddBaseData(pybind11::module& m);
2830
void moduleAddBaseData(pybind11::module& m);
2931

bindings/Sofa/src/SofaPython3/Sofa/Core/Binding_BaseLink.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@
2424

2525
namespace sofapython3 {
2626

27+
/// Forward declaration in pybind11.
28+
/// more details in: https://github.com/sofa-framework/SofaPython3/pull/457
2729
void moduleForwardAddBaseLink(pybind11::module& m);
2830
void moduleAddBaseLink(pybind11::module& m);
2931

bindings/Sofa/src/SofaPython3/Sofa/Core/Binding_BaseMeshTopology.cpp

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121

2222
#include <SofaPython3/Sofa/Core/Binding_Base.h>
2323
#include <SofaPython3/Sofa/Core/Binding_BaseContext.h>
24+
#include <SofaPython3/Sofa/Core/Binding_BaseMeshTopology.h>
2425
#include <SofaPython3/PythonFactory.h>
2526
#include <sofa/core/BaseState.h>
2627
#include <sofa/core/objectmodel/BaseObject.h>
@@ -36,8 +37,21 @@ using namespace sofa::core::topology;
3637

3738
namespace sofapython3 {
3839

40+
41+
auto getPythonClassForBaseMeshTopology(py::module& m)
42+
{
43+
/// Register the BaseData binding into the pybind11 system.
44+
static py::class_<BaseMeshTopology, Topology, py_shared_ptr<BaseMeshTopology>> basemesh(m, "BaseMeshTopology", "API providing all topology-related functions");
45+
return basemesh;
46+
}
47+
48+
void moduleForwardAddBaseMeshTopology(py::module& m)
49+
{
50+
getPythonClassForBaseMeshTopology(m);
51+
}
52+
3953
void moduleAddBaseMeshTopology(py::module& m) {
40-
py::class_<BaseMeshTopology, Topology, py_shared_ptr<BaseMeshTopology>> c (m, "BaseMeshTopology", "API providing all topology-related functions");
54+
auto c = getPythonClassForBaseMeshTopology(m);
4155

4256
/// register the BaseMeshTopology binding in the downcasting subsystem
4357
PythonFactory::registerType<BaseMeshTopology>([](sofa::core::objectmodel::Base* object)

bindings/Sofa/src/SofaPython3/Sofa/Core/Binding_BaseMeshTopology.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@
2424

2525
namespace sofapython3 {
2626

27+
/// Forward declaration in pybind11.
28+
/// more details in: https://github.com/sofa-framework/SofaPython3/pull/457
29+
void moduleForwardAddBaseMeshTopology(pybind11::module &m);
2730
void moduleAddBaseMeshTopology(pybind11::module &m);
2831

2932
} // namespace sofapython3

0 commit comments

Comments
 (0)