Skip to content

Commit

Permalink
[SofaPython3] Remove -at-best- the use of this infamous string conver…
Browse files Browse the repository at this point in the history
…sion while creating an object.
  • Loading branch information
damienmarchal committed Aug 31, 2020
1 parent b5c9cfb commit 6fdc309
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 10 deletions.
25 changes: 22 additions & 3 deletions Plugin/src/SofaPython3/DataHelper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,14 +56,33 @@ std::string toSofaParsableString(const py::handle& p)
return py::repr(p);
}

/// RVO optimized function. Don't care about copy on the return code.
void fillBaseObjectdescription(sofa::core::objectmodel::BaseObjectDescription& desc,
const py::dict& dict)
const py::dict& dict)
{
for(auto kv : dict)
{
desc.setAttribute(py::str(kv.first), toSofaParsableString(kv.second));
}

return;
}

void processKwargsForObjectCreation(const py::dict dict,
py::list& parametersToLink,
py::list& parametersToCopy,
sofa::core::objectmodel::BaseObjectDescription& parametersAsString)
{
auto t = py::detail::get_type_handle(typeid(BaseData), false);
for(auto kv : dict)
{
desc.setAttribute(py::str(kv.first), toSofaParsableString(kv.second));
if (py::isinstance(kv.second, t))
parametersToLink.append(kv.first);
else if (py::isinstance<py::str>(kv.second))
parametersAsString.setAttribute(py::str(kv.first), py::cast<std::string>(kv.second));
else
parametersToCopy.append(kv.first);
}
return;
}

PythonTrampoline::~PythonTrampoline(){}
Expand Down
31 changes: 26 additions & 5 deletions Plugin/src/SofaPython3/DataHelper.h
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,23 @@ namespace sofa {
};

}
}
}

private:
Base::SPtr m_targetBase { nullptr };
std::string m_targetPath {""};
};
}
}
namespace defaulttype
{
template <>
struct DataTypeName<core::objectmodel::PrefabLink>
{
static const char* name() { return "PrefabLink"; }
};

}
}

/////////////////////////////// DECLARATION //////////////////////////////
Expand Down Expand Up @@ -192,7 +208,7 @@ template <typename T> class py_shared_ptr : public sofa::core::sptr<T>

SOFAPYTHON3_API void setItem2D(py::array a, py::slice slice, py::object o);
SOFAPYTHON3_API void setItem2D(py::array a, const py::slice& slice,
const py::slice& slice1, py::object o);
const py::slice& slice1, py::object o);
SOFAPYTHON3_API void setItem1D(py::array a, py::slice slice, py::object o);
SOFAPYTHON3_API void setItem(py::array a, py::slice slice, py::object value);

Expand All @@ -216,11 +232,16 @@ void SOFAPYTHON3_API copyFromListScalar(BaseData& d, const AbstractTypeInfo& nfo

std::string SOFAPYTHON3_API toSofaParsableString(const py::handle& p);

//py::object SOFAPYTHON3_API dataToPython(BaseData* d);

/// RVO optimized function. Don't care about copy on the return code.
void SOFAPYTHON3_API fillBaseObjectdescription(sofa::core::objectmodel::BaseObjectDescription& desc,
const py::dict& dict);
const py::dict& dict);

/// Split the content of the dictionnary 'dict' in three set.
/// On containing the data to parent, one containing the data to copy and on containing the data to parse in the BaseObjectDescription
void SOFAPYTHON3_API processKwargsForObjectCreation(const py::dict dict,
py::list& parametersToLink,
py::list& parametersToCopy,
sofa::core::objectmodel::BaseObjectDescription& parametersAsString);

template<typename T>
void copyScalar(BaseData* a, const AbstractTypeInfo& nfo, py::array_t<T, py::array::c_style> src)
Expand Down
18 changes: 16 additions & 2 deletions bindings/Sofa/src/SofaPython3/Sofa/Core/Binding_Node.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,9 @@ py::object addObjectKwargs(Node* self, const std::string& type, const py::kwargs
/// Prepare the description to hold the different python attributes as data field's
/// arguments then create the object.
BaseObjectDescription desc {type.c_str(), type.c_str()};
fillBaseObjectdescription(desc, kwargs);
py::list parametersToCopy;
py::list parametersToLink;
processKwargsForObjectCreation(kwargs, parametersToLink, parametersToCopy, desc);
auto object = ObjectFactory::getInstance()->createObject(self, &desc);

/// After calling createObject the returned value can be either a nullptr
Expand Down Expand Up @@ -195,6 +197,11 @@ py::object addObjectKwargs(Node* self, const std::string& type, const py::kwargs
{
BaseData* d = object->findData(py::cast<std::string>(a.first));
if(d)
{
if (parametersToLink.contains(a.first))
d->setParent(a.second.cast<BaseData*>());
else if(parametersToCopy.contains(a.first))
PythonFactory::fromPython(d, py::cast<py::object>(a.second));
d->setPersistent(true);
}
return PythonFactory::toPython(object.get());
Expand Down Expand Up @@ -258,14 +265,21 @@ py::object addChildKwargs(Node* self, const std::string& name, const py::kwargs&
if (sofapython3::isProtectedKeyword(name))
throw py::value_error("addChild: Cannot call addChild with name " + name + ": Protected keyword");
BaseObjectDescription desc (name.c_str());
fillBaseObjectdescription(desc,kwargs);
py::list parametersToCopy;
py::list parametersToLink;
processKwargsForObjectCreation(kwargs, parametersToLink, parametersToCopy, desc);
auto node=simpleapi::createChild(self, desc);
checkParamUsage(desc);

for(auto a : kwargs)
{
BaseData* d = node->findData(py::cast<std::string>(a.first));
if(d)
{
if (parametersToLink.contains(a.first))
d->setParent(a.second.cast<BaseData*>());
else if(parametersToCopy.contains(a.first))
PythonFactory::fromPython(d, py::cast<py::object>(a.second));
d->setPersistent(true);
}

Expand Down

0 comments on commit 6fdc309

Please sign in to comment.