Skip to content

Acquire gil for the full scope of the lifetime returned matrix#609

Merged
fredroy merged 1 commit intosofa-framework:masterfrom
bakpaul:26_04_fix_forcefield_binding
Apr 23, 2026
Merged

Acquire gil for the full scope of the lifetime returned matrix#609
fredroy merged 1 commit intosofa-framework:masterfrom
bakpaul:26_04_fix_forcefield_binding

Conversation

@bakpaul
Copy link
Copy Markdown
Contributor

@bakpaul bakpaul commented Apr 21, 2026

In the binding, what is expected from the overloaded funciton is an array that'll be copied. If the gil is released too early the structure can be cleaned before the end of it use. So doing this make sure the structure is kept alive all along. It actually solved a segfault on the following example when launched with runSofa

import Sofa
import numpy as np


class PyForceField(Sofa.Core.ForceFieldVec3d):
    def __init__(self, *args, **kwargs):
        Sofa.Core.ForceFieldVec3d.__init__(self, *args, **kwargs)

    def addForce(self, mechanical_parameters, out_force, position, velocity):
        print("addForce()")

    def addDForce(self, mechanical_parameters, df, dx):
        print("addDForce()")

    def addKToMatrix(self, mechanical_parameters, n_particles, n_dimensions):
        print("addKToMatrix()")
        n_dofs = n_particles * n_dimensions
        return np.zeros((n_dofs, n_dofs, 1))


def createScene(root):
    plugins = root.addChild("Plugins")
    plugins.addObject("RequiredPlugin", pluginName=[
        "Sofa.Component.LinearSolver.Direct",  # Needed to use components [SparseLDLSolver]
        "Sofa.Component.ODESolver.Backward",  # Needed to use components [EulerImplicitSolver]
        "Sofa.Component.StateContainer",  # Needed to use components [MechanicalObject]
        "Sofa.Component.Visual",  # Needed to use components [VisualStyle]
        "Sofa.Component.Mass",
    ])

    root.addObject("VisualStyle")
    root.addObject("DefaultAnimationLoop", bbox=((-2, -2, -2), (2, 2, 2)))

    physics = root.addChild("Physics")
    physics.addObject("EulerImplicitSolver")
    physics.addObject("SparseLDLSolver", template="CompressedRowSparseMatrixd")
    physics.addObject("MechanicalObject", template="Vec3d", position=(0, 0, 0), showObject="true", drawMode="1", showObjectScale="0.1")
    # physics.addObject("UniformMass", name="mass", totalMass=1)
    physics.addObject(PyForceField())

@fredroy fredroy merged commit 23b5efc into sofa-framework:master Apr 23, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants