Chaste / cppwg

An automatic Python wrapper generator for C++ code.
BSD 3-Clause "New" or "Revised" License
41 stars 8 forks source link

Fix unable to find declarations #3

Closed kwabenantim closed 4 months ago

kwabenantim commented 7 months ago

Description Generating wrappers throws errors for some classes: Unable to find declaration Clazz or Unable to find declaration Clazz< 2, 2 >

Error Message

Traceback (most recent call last):
  File "~/Chaste/projects/PyChaste/dynamic/wrapper_generators/generate.py", line 55, in <module>
    generator.generate_wrapper()
  File "~/cppwg/cppwg/generators.py", line 200, in generate_wrapper
    module_writer.write()
  File "~/cppwg/cppwg/writers/module_writer.py", line 112, in write
    class_decl = self.source_ns.class_(fullName.replace(" ",""))
  File "~/.local/lib/python3.10/site-packages/pygccxml/declarations/scopedef.py", line 546, in class_
    self._find_single(
  File "~/.local/lib/python3.10/site-packages/pygccxml/declarations/scopedef.py", line 464, in _find_single
    found = matcher.get_single(decl_matcher, decls, False)
  File "~/.local/lib/python3.10/site-packages/pygccxml/declarations/scopedef.py", line 90, in get_single
    raise runtime_errors.declaration_not_found_t(decl_matcher)
pygccxml.declarations.runtime_errors.declaration_not_found_t: Unable to find declaration. Matcher: [(decl type==class_t) and (name==AbstractCellBasedSimulationModifier< 2, 2 >)]
make[3]: *** [projects/PyChaste/CMakeFiles/project_PyChaste_Python_Bindings.dir/build.make:70: project_PyChaste_Python_Bindings] Error 1
make[2]: *** [CMakeFiles/Makefile2:21607: projects/PyChaste/CMakeFiles/project_PyChaste_Python_Bindings.dir/all] Error 2
make[1]: *** [CMakeFiles/Makefile2:21614: projects/PyChaste/CMakeFiles/project_PyChaste_Python_Bindings.dir/rule] Error 2
make: *** [Makefile:8103: project_PyChaste_Python_Bindings] Error 2
kwabenantim commented 7 months ago

Investigation

kwabenantim commented 7 months ago

There seems to be an issue recognizing template defaults of the form:

template<unsigned  ELEMENT_DIM, unsigned SPACE_DIM=ELEMENT_DIM>
kwabenantim commented 6 months ago

This appears to be a castxml source parser issue for templates like:

template<unsigned  ELEMENT_DIM, unsigned SPACE_DIM=ELEMENT_DIM>

For some classes e.g.

template<unsigned  ELEMENT_DIM, unsigned SPACE_DIM=ELEMENT_DIM>
class AbstractCellBasedSimulationModifier : public Identifiable
{

castxml finds AbstractCellBasedSimulationModifier <2> (but cannot find AbstractCellBasedSimulationModifier <2,2>)

For other classes e.g.

template <unsigned ELEMENT_DIM, unsigned SPACE_DIM = ELEMENT_DIM>
class AbstractCellBasedSimulation : public Identifiable
{

castxml finds AbstractCellBasedSimulation<3,3> (but cannot find AbstractCellBasedSimulation<3>)

The reasons for this are not yet clear.

kwabenantim commented 5 months ago

Classes which resolve to Foo<2> all seem to use macros like EXPORT_TEMPLATE_CLASS_ALL_DIMS or TEMPLATED_CLASS_IS_ABSTRACT_2_UNSIGNED.

kwabenantim commented 5 months ago

Classes with two template arguments that collapse into one e.g. <2, 2> -> <2>:

# pde
AbstractLinearPde
AbstractLinearParabolicPde

# cell_based
AbstractCellBasedSimulationModifier
AbstractForce
AbstractTwoBodyInteractionForce
GeneralisedLinearSpringForce
DifferentialAdhesionGeneralisedLinearSpringForce
AbstractCellPopulationBoundaryCondition
PlaneBoundaryCondition
AttractingPlaneBoundaryCondition
AbstractCellPopulation
AbstractOffLatticeCellPopulation
MeshBasedCellPopulation
OffLatticeSimulation
AbstractCentreBasedDivisionRule
FixedCentreBasedDivisionRule
RandomDirectionCentreBasedDivisionRule
kwabenantim commented 4 months ago

Possible workaround Each ClassInfo object currently has a list of short_names for Python (e.g. AbstractLinearPde2_2) and full_names for C++ (e.g. AbstractLinearPde<2,2>). Both short_names and full_names are used in wrapper code.

The full_names are also used in pygccxml queries to find relevant declarations from parsed source code.

Since castxml doesn't recognize full names like AbstractLinearPde<2,2> in some cases, ClassInfo objects could also be given a list of parsed_names e.g. AbstractLinearPde<2> which are guaranteed to be recognized by castxml (e.g. using a try-catch block).

The parsed_names would then be used in all pygccxml queries and full names will continue to be used in wrapper code.