From a68c096cb1d292331faf92cc358cdb956d06ba3e Mon Sep 17 00:00:00 2001 From: Kwabena N Amponsah Date: Thu, 2 May 2024 12:55:27 +0000 Subject: [PATCH 01/17] #3 log partial template searches --- cppwg/generators.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/cppwg/generators.py b/cppwg/generators.py index 3b539a8..634b061 100644 --- a/cppwg/generators.py +++ b/cppwg/generators.py @@ -285,6 +285,10 @@ def add_class_decls(self) -> None: class_decl = self.source_ns.class_(decl_name) except pygccxml.declarations.runtime_errors.declaration_not_found_t: + logging.warning( + f"Could not find declaration for {decl_name}: trying partial match." + ) + if "=" in class_info.template_signature: # Try to find the class without default template args # e.g. for template class Foo {}; @@ -300,10 +304,10 @@ def add_class_decls(self) -> None: decl_name = ",".join(decl_name.split(",")[0:pos]) + " >" class_decl = self.source_ns.class_(decl_name) + logging.info(f"Found {decl_name}") + else: - logging.error( - f"Could not find class declaration for {decl_name}" - ) + logging.error(f"Could not find declaration for {decl_name}") class_info.decls.append(class_decl) From fa4c995bd25648c3ce66ad7dfa52b503ca2ea7ca Mon Sep 17 00:00:00 2001 From: Kwabena N Amponsah Date: Thu, 2 May 2024 13:04:53 +0000 Subject: [PATCH 02/17] #4 don't log to file --- cppwg/__main__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cppwg/__main__.py b/cppwg/__main__.py index 7271ae0..8f16262 100644 --- a/cppwg/__main__.py +++ b/cppwg/__main__.py @@ -112,7 +112,7 @@ def main() -> None: logging.basicConfig( format="%(levelname)s %(message)s", - handlers=[logging.FileHandler("cppwg.log"), logging.StreamHandler()], + handlers=[logging.StreamHandler()], ) logger = logging.getLogger() From ef8be9bb794b757624e513327a5ff7cd3110dd10 Mon Sep 17 00:00:00 2001 From: Kwabena N Amponsah Date: Thu, 2 May 2024 13:10:44 +0000 Subject: [PATCH 03/17] #5 fix pygccxml version --- cppwg/generators.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cppwg/generators.py b/cppwg/generators.py index 634b061..c7c62f5 100644 --- a/cppwg/generators.py +++ b/cppwg/generators.py @@ -94,7 +94,7 @@ def __init__( r"castxml version \d+\.\d+\.\d+", castxml_version ).group(0) logger.info(castxml_version) - logger.info(f"pygccxml version {pygccxml.version}") + logger.info(f"pygccxml version {pygccxml.__version__}") # Sanitize castxml_cflags self.castxml_cflags: str = "" From 711019f0a31c9b446afa4f40ae60b4e1541f1c31 Mon Sep 17 00:00:00 2001 From: Kwabena N Amponsah Date: Thu, 2 May 2024 15:56:25 +0000 Subject: [PATCH 04/17] #5 add location to Point constructor --- examples/shapes/src/geometry/Point.cpp | 38 ++++++++----------- examples/shapes/src/geometry/Point.hpp | 15 +++----- .../shapes/src/python/test/test_classes.py | 3 ++ 3 files changed, 24 insertions(+), 32 deletions(-) diff --git a/examples/shapes/src/geometry/Point.cpp b/examples/shapes/src/geometry/Point.cpp index aa87aaf..983bd3d 100644 --- a/examples/shapes/src/geometry/Point.cpp +++ b/examples/shapes/src/geometry/Point.cpp @@ -1,62 +1,54 @@ #include "Point.hpp" -template -Point::Point() : - mIndex(0), - mLocation() +template +Point::Point(std::array location) + : mIndex(0) + , mLocation(location) { - mLocation[0] = 0.0; - mLocation[1] = 0.0; - if(DIM==3) - { - mLocation[2] = 0.0; - } } -template -Point::Point(double x, double y, double z) : - mIndex(0), - mLocation() +template +Point::Point(double x, double y, double z) + : mIndex(0) + , mLocation() { mLocation[0] = x; mLocation[1] = y; - if(DIM==3) - { + if (DIM == 3) { mLocation[2] = z; } } -template +template Point::~Point() { - } -template +template std::array Point::GetLocation() const { return mLocation; } -template +template const std::array& Point::rGetLocation() const { return mLocation; } -template +template unsigned Point::GetIndex() const { return mIndex; } -template +template void Point::SetIndex(unsigned index) { mIndex = index; } -template +template void Point::SetLocation(const std::array& rLocation) { mLocation = rLocation; diff --git a/examples/shapes/src/geometry/Point.hpp b/examples/shapes/src/geometry/Point.hpp index 018731e..4c1e9c5 100644 --- a/examples/shapes/src/geometry/Point.hpp +++ b/examples/shapes/src/geometry/Point.hpp @@ -6,11 +6,9 @@ /** * A point in DIM dimensional space */ -template -class Point -{ +template +class Point { private: - /** * Point index */ @@ -22,16 +20,15 @@ class Point std::array mLocation; public: - /** * Default Constructor */ - Point(); + Point(std::array location = { 0.0 }); /** - * Constructor + * Constructor with coordinates */ - Point(double x, double y, double z=0.0); + Point(double x, double y, double z = 0.0); /** * Destructor @@ -64,4 +61,4 @@ class Point void SetLocation(const std::array& rLocation); }; -#endif // _POINT_HPP +#endif // _POINT_HPP diff --git a/examples/shapes/src/python/test/test_classes.py b/examples/shapes/src/python/test/test_classes.py index a173760..3f9a134 100644 --- a/examples/shapes/src/python/test/test_classes.py +++ b/examples/shapes/src/python/test/test_classes.py @@ -9,6 +9,9 @@ class TestClasses(unittest.TestCase): def testGeometry(self): + p0 = pyshapes.geometry.Point2() + self.assertTrue(p0.GetLocation() == [0.0, 0.0]) + p1 = pyshapes.geometry.Point2(0.0, 0.0) p2 = pyshapes.geometry.Point2(1.0, 0.0) p3 = pyshapes.geometry.Point2(0.0, 1.0) From 1c7844d26b7fe7f228771db2d8c2be3940dea72a Mon Sep 17 00:00:00 2001 From: Kwabena N Amponsah Date: Thu, 2 May 2024 15:57:09 +0000 Subject: [PATCH 05/17] #5 pretty example header guards --- examples/shapes/src/math_funcs/SimpleMathFunctions.hpp | 6 +++--- examples/shapes/src/primitives/Cuboid.hpp | 6 +++--- examples/shapes/src/primitives/Rectangle.hpp | 6 +++--- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/examples/shapes/src/math_funcs/SimpleMathFunctions.hpp b/examples/shapes/src/math_funcs/SimpleMathFunctions.hpp index 8451bd9..bae076d 100644 --- a/examples/shapes/src/math_funcs/SimpleMathFunctions.hpp +++ b/examples/shapes/src/math_funcs/SimpleMathFunctions.hpp @@ -1,5 +1,5 @@ -#ifndef _SIMPLEMATHFUNCTIONS_HPP -#define _SIMPLEMATHFUNCTIONS_HPP +#ifndef _SIMPLE_MATH_FUNCTIONS_HPP +#define _SIMPLE_MATH_FUNCTIONS_HPP /** * Add the two input numbers and return the result @@ -12,4 +12,4 @@ inline double add(double i = 1.0, double j = 2.0) return i + j; } -#endif // _SIMPLEMATHFUNCTIONS_HPP +#endif // _SIMPLE_MATH_FUNCTIONS_HPP diff --git a/examples/shapes/src/primitives/Cuboid.hpp b/examples/shapes/src/primitives/Cuboid.hpp index 6b3d4b9..3d0a409 100644 --- a/examples/shapes/src/primitives/Cuboid.hpp +++ b/examples/shapes/src/primitives/Cuboid.hpp @@ -1,5 +1,5 @@ -#ifndef _Cuboid_HPP -#define _Cuboid_HPP +#ifndef _CUBOID_HPP +#define _CUBOID_HPP #include "Shape.hpp" @@ -23,4 +23,4 @@ class Cuboid : public Shape<3> }; -#endif // _Cuboid_HPP +#endif // _CUBOID_HPP diff --git a/examples/shapes/src/primitives/Rectangle.hpp b/examples/shapes/src/primitives/Rectangle.hpp index 692877a..a990a90 100644 --- a/examples/shapes/src/primitives/Rectangle.hpp +++ b/examples/shapes/src/primitives/Rectangle.hpp @@ -1,5 +1,5 @@ -#ifndef _Rectangle_HPP -#define _Rectangle_HPP +#ifndef _RECTANGLE_HPP +#define _RECTANGLE_HPP #include "Shape.hpp" @@ -23,4 +23,4 @@ class Rectangle : public Shape<2> }; -#endif // _Rectangle_HPP +#endif // _RECTANGLE_HPP From f0f251fd607924f60ee7fa4dc889ab485d297788 Mon Sep 17 00:00:00 2001 From: Kwabena N Amponsah Date: Thu, 2 May 2024 16:57:08 +0000 Subject: [PATCH 06/17] #5 add DIM in Point constructor default args --- examples/shapes/src/geometry/Point.cpp | 5 ++--- examples/shapes/src/geometry/Point.hpp | 4 ++-- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/examples/shapes/src/geometry/Point.cpp b/examples/shapes/src/geometry/Point.cpp index 983bd3d..098b13d 100644 --- a/examples/shapes/src/geometry/Point.cpp +++ b/examples/shapes/src/geometry/Point.cpp @@ -1,9 +1,8 @@ #include "Point.hpp" template -Point::Point(std::array location) - : mIndex(0) - , mLocation(location) +Point::Point() + : Point(0.0, 0.0, 0.0) { } diff --git a/examples/shapes/src/geometry/Point.hpp b/examples/shapes/src/geometry/Point.hpp index 4c1e9c5..0f5e19c 100644 --- a/examples/shapes/src/geometry/Point.hpp +++ b/examples/shapes/src/geometry/Point.hpp @@ -23,12 +23,12 @@ class Point { /** * Default Constructor */ - Point(std::array location = { 0.0 }); + Point(); /** * Constructor with coordinates */ - Point(double x, double y, double z = 0.0); + Point(double x, double y, double z = DIM - DIM); /** * Destructor From a96d1530d85f7301577f9482b25c73d1f3a16027 Mon Sep 17 00:00:00 2001 From: Kwabena N Amponsah Date: Thu, 2 May 2024 19:52:37 +0000 Subject: [PATCH 07/17] #5 add template names in default args --- examples/shapes/src/geometry/Point.hpp | 9 ++++--- examples/shapes/src/primitives/Shape.cpp | 31 ++++++++++++++---------- examples/shapes/src/primitives/Shape.hpp | 18 ++++++++------ 3 files changed, 33 insertions(+), 25 deletions(-) diff --git a/examples/shapes/src/geometry/Point.hpp b/examples/shapes/src/geometry/Point.hpp index 0f5e19c..5ffb56f 100644 --- a/examples/shapes/src/geometry/Point.hpp +++ b/examples/shapes/src/geometry/Point.hpp @@ -7,7 +7,8 @@ * A point in DIM dimensional space */ template -class Point { +class Point +{ private: /** * Point index @@ -28,7 +29,7 @@ class Point { /** * Constructor with coordinates */ - Point(double x, double y, double z = DIM - DIM); + Point(double x, double y, double z = (DIM - DIM)); /** * Destructor @@ -43,7 +44,7 @@ class Point { /** * Return the const location */ - const std::array& rGetLocation() const; + const std::array &rGetLocation() const; /** * Return the index @@ -58,7 +59,7 @@ class Point { /** * Set the location */ - void SetLocation(const std::array& rLocation); + void SetLocation(const std::array &rLocation); }; #endif // _POINT_HPP diff --git a/examples/shapes/src/primitives/Shape.cpp b/examples/shapes/src/primitives/Shape.cpp index 626ecb6..4ee1a8a 100644 --- a/examples/shapes/src/primitives/Shape.cpp +++ b/examples/shapes/src/primitives/Shape.cpp @@ -1,42 +1,47 @@ +#include + #include "Shape.hpp" -template -Shape::Shape() : - mIndex(0), - mVertices() +template +Shape::Shape() : mIndex(0), + mVertices() { - } -template +template Shape::~Shape() { - } -template +template unsigned Shape::GetIndex() const { return mIndex; } -template -const std::vector > >& Shape::rGetVertices() const +template +const std::vector>> &Shape::rGetVertices() const { return mVertices; } -template +template void Shape::SetIndex(unsigned index) { mIndex = index; } -template -void Shape::SetVertices(const std::vector > >& rVertices) +template +void Shape::SetVertices(const std::vector>> &rVertices) { mVertices = rVertices; } +template +void Shape::AddVertex(std::shared_ptr> point) +{ + this->mVertices.push_back(point); +} + template class Shape<2>; template class Shape<3>; diff --git a/examples/shapes/src/primitives/Shape.hpp b/examples/shapes/src/primitives/Shape.hpp index 798686b..19538c7 100644 --- a/examples/shapes/src/primitives/Shape.hpp +++ b/examples/shapes/src/primitives/Shape.hpp @@ -8,11 +8,10 @@ /** * A DIM dimensional shape */ -template +template class Shape { protected: - /** * The shape index */ @@ -21,10 +20,9 @@ class Shape /** * The shape vertices */ - std::vector > > mVertices; + std::vector>> mVertices; public: - /** * Default Constructor */ @@ -43,7 +41,7 @@ class Shape /** * Return the shape vertices */ - const std::vector > >& rGetVertices() const; + const std::vector>> &rGetVertices() const; /** * Set the shape index @@ -53,8 +51,12 @@ class Shape /** * Set the shape vertices */ - void SetVertices(const std::vector > >& rVertices); -}; + void SetVertices(const std::vector>> &rVertices); + /** + * Add a single vertex to the shape + */ + void AddVertex(std::shared_ptr> point = std::make_shared>()); +}; -#endif // _SHAPE_HPP +#endif // _SHAPE_HPP From 7efe7eaa3c406d6ef1b713589e02eddbd531400e Mon Sep 17 00:00:00 2001 From: Kwabena N Amponsah Date: Thu, 2 May 2024 19:57:04 +0000 Subject: [PATCH 08/17] #5 replace template names in default args --- cppwg/input/cpp_type_info.py | 5 ++- cppwg/input/info_helper.py | 12 +++++++ cppwg/writers/class_writer.py | 24 ++++++------- cppwg/writers/constructor_writer.py | 45 ++++++++++++++++--------- cppwg/writers/method_writer.py | 52 +++++++++++++++-------------- 5 files changed, 84 insertions(+), 54 deletions(-) diff --git a/cppwg/input/cpp_type_info.py b/cppwg/input/cpp_type_info.py index d5d7578..fcd166d 100644 --- a/cppwg/input/cpp_type_info.py +++ b/cppwg/input/cpp_type_info.py @@ -21,8 +21,10 @@ class CppTypeInfo(BaseInfo): The name override specified in config e.g. "CustomFoo" -> "Foo" template_signature : str The template signature of the type e.g. "" + template_params : List[str] + List of template parameters e.g. ["DIM_A", "DIM_B"] template_arg_lists : List[List[Any]] - List of template replacement arguments for the type e.g. [[2, 2], [3, 3]] + List of template replacement arguments e.g. [[2, 2], [3, 3]] decls : pygccxml.declarations.declaration_t The pygccxml declarations associated with this type, one per template arg if templated """ @@ -36,6 +38,7 @@ def __init__(self, name: str, type_config: Optional[Dict[str, Any]] = None): self.source_file: Optional[str] = None self.name_override: Optional[str] = None self.template_signature: Optional[str] = None + self.template_params: Optional[List[str]] = None self.template_arg_lists: Optional[List[List[Any]]] = None self.decls: Optional[List["declaration_t"]] = None # noqa: F821 diff --git a/cppwg/input/info_helper.py b/cppwg/input/info_helper.py index 9b81d5a..b2883d8 100644 --- a/cppwg/input/info_helper.py +++ b/cppwg/input/info_helper.py @@ -134,4 +134,16 @@ def extract_templates_from_source(self, feature_info: BaseInfo) -> None: feature_info.template_signature = template_substitution[ "signature" ] + + # Extract ["DIM_A", "DIM_B"] from "" + template_params = [] + for tp in template_substitution["signature"].split(","): + template_params.append( + tp.replace("<", "") + .replace(">", "") + .split(" ")[1] + .split("=")[0] + .strip() + ) + feature_info.template_params = template_params break diff --git a/cppwg/writers/class_writer.py b/cppwg/writers/class_writer.py index 677f44b..fa97619 100644 --- a/cppwg/writers/class_writer.py +++ b/cppwg/writers/class_writer.py @@ -147,7 +147,7 @@ def add_cpp_header(self, class_full_name: str, class_short_name: str) -> None: ) def add_virtual_overrides( - self, class_decl: "class_t", short_class_name: str # noqa: F821 + self, template_idx: int ) -> List["member_function_t"]: # noqa: F821 """ Add virtual "trampoline" overrides for the class. @@ -157,10 +157,8 @@ def add_virtual_overrides( Parameters ---------- - class_decl : class_t - The class declaration - short_class_name : str - The short name of the class e.g. Foo2_2 + template_idx : int + The index of the template in the class info Returns ------- @@ -170,6 +168,8 @@ def add_virtual_overrides( return_types: List[str] = [] # e.g. ["void", "unsigned int", "::Bar<2> *"] # Collect all virtual methods and their return types + class_decl = self.class_info.decls[template_idx] + for member_function in class_decl.member_functions(allow_empty=True): is_pure_virtual = member_function.virtuality == "pure virtual" is_virtual = member_function.virtuality == "virtual" @@ -192,13 +192,14 @@ def add_virtual_overrides( self.cpp_string += "\n" # Override virtual methods + short_name = self.class_info.short_names[template_idx] if methods_needing_override: # Add virtual override class, e.g.: # class Foo_Overrides : public Foo { # public: # using Foo::Foo; override_header_dict = { - "class_short_name": short_class_name, + "class_short_name": short_name, "class_base_name": self.class_info.name, } @@ -217,10 +218,9 @@ def add_virtual_overrides( for method in methods_needing_override: method_writer = CppMethodWrapperWriter( self.class_info, + template_idx, method, - class_decl, self.wrapper_templates, - short_class_name, ) self.cpp_string += method_writer.generate_virtual_override_wrapper() @@ -284,7 +284,7 @@ def write(self, work_dir: str) -> None: # Find and define virtual function "trampoline" overrides methods_needing_override: List["member_function_t"] = ( # noqa: F821 - self.add_virtual_overrides(class_decl, short_name) + self.add_virtual_overrides(idx) ) # Add the virtual "trampoline" overrides from "Foo_Overrides" to @@ -331,10 +331,9 @@ def write(self, work_dir: str) -> None: ): constructor_writer = CppConstructorWrapperWriter( self.class_info, + idx, constructor, - class_decl, self.wrapper_templates, - short_name, ) self.cpp_string += constructor_writer.generate_wrapper() @@ -350,10 +349,9 @@ def write(self, work_dir: str) -> None: method_writer = CppMethodWrapperWriter( self.class_info, + idx, member_function, - class_decl, self.wrapper_templates, - short_name, ) self.cpp_string += method_writer.generate_wrapper() diff --git a/cppwg/writers/constructor_writer.py b/cppwg/writers/constructor_writer.py index a0a2a54..7115836 100644 --- a/cppwg/writers/constructor_writer.py +++ b/cppwg/writers/constructor_writer.py @@ -3,10 +3,7 @@ from typing import Dict, Optional from pygccxml import declarations -from pygccxml.declarations.calldef_members import constructor_t -from pygccxml.declarations.class_declaration import class_t -from cppwg.input.class_info import CppClassInfo from cppwg.writers.base_writer import CppBaseWrapperWriter @@ -18,35 +15,46 @@ class CppConstructorWrapperWriter(CppBaseWrapperWriter): ---------- class_info : ClassInfo The class information for the class containing the constructor - ctor_decl : constructor_t + template_idx: int + The index of the template in class_info + ctor_decl : pygccxml.declarations.constructor_t The pygccxml declaration object for the constructor - class_decl : class_t + class_decl : pygccxml.declarations.class_t The class declaration for the class containing the constructor wrapper_templates : Dict[str, str] String templates with placeholders for generating wrapper code class_short_name : Optional[str] The short name of the class e.g. 'Foo2_2' + template_params: Optional[List[str]] + The template params for the class e.g. ['DIM_A', 'DIM_B'] + template_args: Optional[List[str]] + The template args for the class e.g. ['2', '2'] """ def __init__( self, - class_info: CppClassInfo, - ctor_decl: constructor_t, - class_decl: class_t, + class_info: "CppClassInfo", # noqa: F821 + template_idx: int, + ctor_decl: "constructor_t", # noqa: F821 wrapper_templates: Dict[str, str], - class_short_name: Optional[str] = None, ) -> None: super(CppConstructorWrapperWriter, self).__init__(wrapper_templates) - self.class_info: CppClassInfo = class_info - self.ctor_decl: constructor_t = ctor_decl - self.class_decl: class_t = class_decl + self.class_info: "CppClassInfo" = class_info # noqa: F821 + self.ctor_decl: "constructor_t" = ctor_decl # noqa: F821 + self.class_decl: "class_t" = class_info.decls[template_idx] # noqa: F821 - self.class_short_name = class_short_name + self.class_short_name = class_info.short_names[template_idx] if self.class_short_name is None: self.class_short_name = self.class_decl.name + self.template_params = class_info.template_params + + self.template_args = None + if class_info.template_arg_lists: + self.template_args = class_info.template_arg_lists[template_idx] + def exclusion_criteria(self) -> bool: """ Check if the constructor should be excluded from the wrapper code. @@ -148,8 +156,15 @@ def generate_wrapper(self) -> str: default_args += f', py::arg("{arg.name}")' if arg.default_value is not None: - # TODO: Fix in default args (see method_writer) - default_args += f" = {arg.default_value}" + default_value = str(arg.default_value) + + if self.template_params: + for param, val in zip(self.template_params, self.template_args): + default_value = default_value.replace( + self.class_info.name + "::" + param, str(val) + ).replace(param, str(val)) + + default_args += f" = {default_value}" wrapper_string += default_args + ")\n" diff --git a/cppwg/writers/method_writer.py b/cppwg/writers/method_writer.py index d61e189..cc7aede 100644 --- a/cppwg/writers/method_writer.py +++ b/cppwg/writers/method_writer.py @@ -3,10 +3,7 @@ from typing import Dict, Optional from pygccxml import declarations -from pygccxml.declarations.calldef_members import member_function_t -from pygccxml.declarations.class_declaration import class_t -from cppwg.input.class_info import CppClassInfo from cppwg.writers.base_writer import CppBaseWrapperWriter @@ -18,35 +15,46 @@ class CppMethodWrapperWriter(CppBaseWrapperWriter): ---------- class_info : ClassInfo The class information for the class containing the method - method_decl : member_function_t + template_idx: int + The index of the template in class_info + method_decl : [pygccxml.declarations.member_function_t] The pygccxml declaration object for the method - class_decl : class_t + class_decl : [pygccxml.declarations.class_t] The class declaration for the class containing the method wrapper_templates : Dict[str, str] String templates with placeholders for generating wrapper code class_short_name : Optional[str] The short name of the class e.g. 'Foo2_2' + template_params: Optional[List[str]] + The template params for the class e.g. ['DIM_A', 'DIM_B'] + template_args: Optional[List[str]] + The template args for the class e.g. ['2', '2'] """ def __init__( self, - class_info: CppClassInfo, - method_decl: member_function_t, - class_decl: class_t, + class_info: "CppClassInfo", # noqa: F821 + template_idx: int, + method_decl: "member_function_t", # noqa: F821 wrapper_templates: Dict[str, str], - class_short_name: Optional[str] = None, ) -> None: super(CppMethodWrapperWriter, self).__init__(wrapper_templates) - self.class_info: CppClassInfo = class_info - self.method_decl: member_function_t = method_decl - self.class_decl: class_t = class_decl + self.class_info: "CppClassInfo" = class_info # noqa: F821 + self.method_decl: "member_function_t" = method_decl # noqa: F821 + self.class_decl: "class_t" = class_info.decls[template_idx] # noqa: F821 - self.class_short_name: str = class_short_name + self.class_short_name = class_info.short_names[template_idx] if self.class_short_name is None: self.class_short_name = self.class_decl.name + self.template_params = class_info.template_params + + self.template_args = None + if class_info.template_arg_lists: + self.template_args = class_info.template_arg_lists[template_idx] + def exclusion_criteria(self) -> bool: """ Check if the method should be excluded from the wrapper code. @@ -136,23 +144,17 @@ def generate_wrapper(self) -> str: # Default args e.g. py::arg("d") = 1.0 default_args = "" if not self.default_arg_exclusion_criteria(): - for arg, arg_type in zip( - self.method_decl.arguments, self.method_decl.argument_types - ): + for arg in self.method_decl.arguments: default_args += f', py::arg("{arg.name}")' if arg.default_value is not None: default_value = str(arg.default_value) - # Hack for missing template in default args - # e.g. Foo<2>::bar(Bar<2> const & b = Bar()) - # TODO: Make more robust - arg_type_str = str(arg_type).replace(" ", "") - if "" in default_value: - if "<2>" in arg_type_str: - default_value = default_value.replace("", "<2>") - elif "<3>" in arg_type_str: - default_value = default_value.replace("", "<3>") + if self.template_params: + for param, val in zip(self.template_params, self.template_args): + default_value = default_value.replace( + self.class_info.name + "::" + param, str(val) + ).replace(param, str(val)) default_args += f" = {default_value}" From 9d534f62185da54374c16c05dd7b15c382ad1b1c Mon Sep 17 00:00:00 2001 From: Kwabena N Amponsah Date: Thu, 2 May 2024 19:58:00 +0000 Subject: [PATCH 09/17] #5 Update generated wrappers --- examples/shapes/wrapper/geometry/Point2.cppwg.cpp | 2 +- examples/shapes/wrapper/geometry/Point3.cppwg.cpp | 2 +- examples/shapes/wrapper/primitives/Shape2.cppwg.cpp | 4 ++++ examples/shapes/wrapper/primitives/Shape3.cppwg.cpp | 4 ++++ 4 files changed, 10 insertions(+), 2 deletions(-) diff --git a/examples/shapes/wrapper/geometry/Point2.cppwg.cpp b/examples/shapes/wrapper/geometry/Point2.cppwg.cpp index cf20feb..12b69e7 100644 --- a/examples/shapes/wrapper/geometry/Point2.cppwg.cpp +++ b/examples/shapes/wrapper/geometry/Point2.cppwg.cpp @@ -11,7 +11,7 @@ PYBIND11_DECLARE_HOLDER_TYPE(T, std::shared_ptr); void register_Point2_class(py::module &m){ py::class_ >(m, "Point2") .def(py::init< >()) - .def(py::init(), py::arg("x"), py::arg("y"), py::arg("z") = 0.) + .def(py::init(), py::arg("x"), py::arg("y"), py::arg("z") = (2 - 2)) .def( "GetLocation", (::std::array(Point2::*)() const ) &Point2::GetLocation, diff --git a/examples/shapes/wrapper/geometry/Point3.cppwg.cpp b/examples/shapes/wrapper/geometry/Point3.cppwg.cpp index af5fd03..04f277f 100644 --- a/examples/shapes/wrapper/geometry/Point3.cppwg.cpp +++ b/examples/shapes/wrapper/geometry/Point3.cppwg.cpp @@ -11,7 +11,7 @@ PYBIND11_DECLARE_HOLDER_TYPE(T, std::shared_ptr); void register_Point3_class(py::module &m){ py::class_ >(m, "Point3") .def(py::init< >()) - .def(py::init(), py::arg("x"), py::arg("y"), py::arg("z") = 0.) + .def(py::init(), py::arg("x"), py::arg("y"), py::arg("z") = (3 - 3)) .def( "GetLocation", (::std::array(Point3::*)() const ) &Point3::GetLocation, diff --git a/examples/shapes/wrapper/primitives/Shape2.cppwg.cpp b/examples/shapes/wrapper/primitives/Shape2.cppwg.cpp index 76d5474..cfb6a0d 100644 --- a/examples/shapes/wrapper/primitives/Shape2.cppwg.cpp +++ b/examples/shapes/wrapper/primitives/Shape2.cppwg.cpp @@ -27,5 +27,9 @@ py::class_ >(m, "Shape2") "SetVertices", (void(Shape2::*)(::std::vector>> const &)) &Shape2::SetVertices, " " , py::arg("rVertices") ) + .def( + "AddVertex", + (void(Shape2::*)(::std::shared_ptr>)) &Shape2::AddVertex, + " " , py::arg("point") = std::make_shared>() ) ; } diff --git a/examples/shapes/wrapper/primitives/Shape3.cppwg.cpp b/examples/shapes/wrapper/primitives/Shape3.cppwg.cpp index b3e81cf..cb81bf3 100644 --- a/examples/shapes/wrapper/primitives/Shape3.cppwg.cpp +++ b/examples/shapes/wrapper/primitives/Shape3.cppwg.cpp @@ -27,5 +27,9 @@ py::class_ >(m, "Shape3") "SetVertices", (void(Shape3::*)(::std::vector>> const &)) &Shape3::SetVertices, " " , py::arg("rVertices") ) + .def( + "AddVertex", + (void(Shape3::*)(::std::shared_ptr>)) &Shape3::AddVertex, + " " , py::arg("point") = std::make_shared>() ) ; } From 4f0079dd3b9c1cf52b059cd25461b708c7abdff0 Mon Sep 17 00:00:00 2001 From: Kwabena N Amponsah Date: Thu, 2 May 2024 20:00:47 +0000 Subject: [PATCH 10/17] #5 remove unused imports --- cppwg/writers/constructor_writer.py | 2 +- cppwg/writers/method_writer.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cppwg/writers/constructor_writer.py b/cppwg/writers/constructor_writer.py index 7115836..931089e 100644 --- a/cppwg/writers/constructor_writer.py +++ b/cppwg/writers/constructor_writer.py @@ -1,6 +1,6 @@ """Wrapper code writer for C++ class constructors.""" -from typing import Dict, Optional +from typing import Dict from pygccxml import declarations diff --git a/cppwg/writers/method_writer.py b/cppwg/writers/method_writer.py index cc7aede..a8da461 100644 --- a/cppwg/writers/method_writer.py +++ b/cppwg/writers/method_writer.py @@ -1,6 +1,6 @@ """Wrapper code writer for C++ methods.""" -from typing import Dict, Optional +from typing import Dict from pygccxml import declarations From 5eb914ea3367df7e28da97242f3d3ab1d8441f73 Mon Sep 17 00:00:00 2001 From: Kwabena N Amponsah Date: Thu, 2 May 2024 21:00:52 +0000 Subject: [PATCH 11/17] #5 replace default arg template names on word boundaries --- cppwg/writers/constructor_writer.py | 17 ++++++++++++++--- cppwg/writers/method_writer.py | 17 ++++++++++++++--- 2 files changed, 28 insertions(+), 6 deletions(-) diff --git a/cppwg/writers/constructor_writer.py b/cppwg/writers/constructor_writer.py index 931089e..b874378 100644 --- a/cppwg/writers/constructor_writer.py +++ b/cppwg/writers/constructor_writer.py @@ -1,5 +1,6 @@ """Wrapper code writer for C++ class constructors.""" +import re from typing import Dict from pygccxml import declarations @@ -159,10 +160,20 @@ def generate_wrapper(self) -> str: default_value = str(arg.default_value) if self.template_params: + # Check for template params in default value for param, val in zip(self.template_params, self.template_args): - default_value = default_value.replace( - self.class_info.name + "::" + param, str(val) - ).replace(param, str(val)) + if param in default_value: + # Replace e.g. Foo::DIM_A -> 2 + default_value = re.sub( + f"\\b{self.class_info.name}::{param}\\b", + str(val), + default_value, + ) + + # Replace e.g. -> <2> + default_value = re.sub( + f"\\b{param}\\b", f"{val}", default_value + ) default_args += f" = {default_value}" diff --git a/cppwg/writers/method_writer.py b/cppwg/writers/method_writer.py index a8da461..30e0215 100644 --- a/cppwg/writers/method_writer.py +++ b/cppwg/writers/method_writer.py @@ -1,5 +1,6 @@ """Wrapper code writer for C++ methods.""" +import re from typing import Dict from pygccxml import declarations @@ -151,10 +152,20 @@ def generate_wrapper(self) -> str: default_value = str(arg.default_value) if self.template_params: + # Check for template params in default value for param, val in zip(self.template_params, self.template_args): - default_value = default_value.replace( - self.class_info.name + "::" + param, str(val) - ).replace(param, str(val)) + if param in default_value: + # Replace e.g. Foo::DIM_A -> 2 + default_value = re.sub( + f"\\b{self.class_info.name}::{param}\\b", + str(val), + default_value, + ) + + # Replace e.g. -> <2> + default_value = re.sub( + f"\\b{param}\\b", f"{val}", default_value + ) default_args += f" = {default_value}" From 67b53ae67f45e99b7832c1e2e8c68cb8d720bac5 Mon Sep 17 00:00:00 2001 From: Kwabena N Amponsah Date: Fri, 3 May 2024 08:50:21 +0000 Subject: [PATCH 12/17] #4 rename exclusion_criteria methods to exclude --- cppwg/writers/base_writer.py | 2 +- cppwg/writers/constructor_writer.py | 6 +++--- cppwg/writers/free_function_writer.py | 6 +++--- cppwg/writers/method_writer.py | 6 +++--- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/cppwg/writers/base_writer.py b/cppwg/writers/base_writer.py index 336d314..620dd5d 100644 --- a/cppwg/writers/base_writer.py +++ b/cppwg/writers/base_writer.py @@ -55,7 +55,7 @@ def tidy_name(self, name: str) -> str: return name # TODO: This method is currently a placeholder. Consider implementing or removing. - def default_arg_exclusion_criteria(self) -> bool: + def exclude_default_args(self) -> bool: """ Check if default arguments should be excluded from the wrapper code. diff --git a/cppwg/writers/constructor_writer.py b/cppwg/writers/constructor_writer.py index b874378..1ae240d 100644 --- a/cppwg/writers/constructor_writer.py +++ b/cppwg/writers/constructor_writer.py @@ -56,7 +56,7 @@ def __init__( if class_info.template_arg_lists: self.template_args = class_info.template_arg_lists[template_idx] - def exclusion_criteria(self) -> bool: + def exclude(self) -> bool: """ Check if the constructor should be excluded from the wrapper code. @@ -139,7 +139,7 @@ def generate_wrapper(self) -> str: The constructor wrapper code. """ # Skip excluded constructors - if self.exclusion_criteria(): + if self.exclude(): return "" # Get the arg signature e.g. "int, bool" @@ -152,7 +152,7 @@ def generate_wrapper(self) -> str: # Default args e.g. py::arg("i") = 1 default_args = "" - if not self.default_arg_exclusion_criteria(): + if not self.exclude_default_args(): for arg in self.ctor_decl.arguments: default_args += f', py::arg("{arg.name}")' diff --git a/cppwg/writers/free_function_writer.py b/cppwg/writers/free_function_writer.py index 690c0aa..eb371ec 100644 --- a/cppwg/writers/free_function_writer.py +++ b/cppwg/writers/free_function_writer.py @@ -38,7 +38,7 @@ def generate_wrapper(self) -> str: The updated C++ wrapper code string """ # Skip this free function if it uses any excluded arg types or return types - if self.exclusion_criteria(): + if self.exclude(): return "" # Pybind11 def type e.g. "_static" for def_static() @@ -48,7 +48,7 @@ def generate_wrapper(self) -> str: # e.g. without default values: ', py::arg("foo"), py::arg("bar")' # e.g. with default values: ', py::arg("foo") = 1, py::arg("bar") = 2' default_args = "" - if not self.default_arg_exclusion_criteria(): + if not self.exclude_default_args(): for argument in self.free_function_info.decls[0].arguments: default_args += f', py::arg("{argument.name}")' if argument.default_value is not None: @@ -65,7 +65,7 @@ def generate_wrapper(self) -> str: return wrapper_string - def exclusion_criteria(self) -> bool: + def exclude(self) -> bool: """ Check if the function should be excluded from the wrapper code. diff --git a/cppwg/writers/method_writer.py b/cppwg/writers/method_writer.py index 30e0215..69bc6bb 100644 --- a/cppwg/writers/method_writer.py +++ b/cppwg/writers/method_writer.py @@ -56,7 +56,7 @@ def __init__( if class_info.template_arg_lists: self.template_args = class_info.template_arg_lists[template_idx] - def exclusion_criteria(self) -> bool: + def exclude(self) -> bool: """ Check if the method should be excluded from the wrapper code. @@ -118,7 +118,7 @@ def generate_wrapper(self) -> str: The method wrapper code. """ # Skip excluded methods - if self.exclusion_criteria(): + if self.exclude(): return "" # Pybind11 def type e.g. "_static" for def_static() @@ -144,7 +144,7 @@ def generate_wrapper(self) -> str: # Default args e.g. py::arg("d") = 1.0 default_args = "" - if not self.default_arg_exclusion_criteria(): + if not self.exclude_default_args(): for arg in self.method_decl.arguments: default_args += f', py::arg("{arg.name}")' From bdb378f06951ba937e3be7d0949aada6f68fd613 Mon Sep 17 00:00:00 2001 From: Kwabena N Amponsah Date: Fri, 3 May 2024 10:38:19 +0000 Subject: [PATCH 13/17] #5 annotate package_info.yaml --- examples/shapes/wrapper/package_info.yaml | 52 ++++++++++++++++++++--- 1 file changed, 47 insertions(+), 5 deletions(-) diff --git a/examples/shapes/wrapper/package_info.yaml b/examples/shapes/wrapper/package_info.yaml index 43711d2..237762d 100644 --- a/examples/shapes/wrapper/package_info.yaml +++ b/examples/shapes/wrapper/package_info.yaml @@ -1,5 +1,22 @@ -name: pyshapes # Unique name prepended to all modules +name: pyshapes # Package name: prepended to all modules. + +# Smart pointer type for PYBIND11_DECLARE_HOLDER_TYPE in all wrappers. smart_ptr_type: std::shared_ptr +# Default value of pybind11::return_value_policy for pointers. +pointer_call_policy: reference +# Default value of pybind11::return_value_policy for references. +reference_call_policy: reference_internal + +# Set True to include the common include file (all headers) in all wrappers. +common_include_file: False +# Headers to be included in all wrappers. +source_includes: + - + +# Exclude default arguments from method signatures. +exclude_default_args: False + +# Signature/replacement settings for explicit template instantiations. template_substitutions: - signature: replacement: [[2], [3]] @@ -7,20 +24,45 @@ template_substitutions: replacement: [[2, 2], [3, 3]] modules: - - name: math_funcs # Name of the module - source_locations: # Only use decls with hpp files found in these directories. Leave blank for 'cppwg_ALL' - classes: # Classes to include. Blank means none, cppwg_ALL means any found - free_functions: cppwg_ALL # Free functions to include. Blank means none, cppwg_ALL means any found + - name: math_funcs # Module name + # Restrict to headers from these directories. Blank means unrestricted. + source_locations: + # List of classes to wrap. Blank means none, CPPWG_ALL means discover all. + classes: + # List of free functions to wrap. Blank means none, CPPWG_ALL means discover all. + free_functions: CPPWG_ALL + - name: geometry source_locations: classes: - name: Point + # Name of class source file. Not required if class name matches file name. + source_file: Point.hpp + # Additional headers to include in this class wrapper. + source_includes: + - + # List of methods that should not be wrapped. + excluded_methods: + - ExcludedMethod + + # Exclude any constructors that have these arg types. + # constructor_arg_type_excludes: + # - double + + # Path to custom script for generating wrappers for this class. + # CPPWG_SOURCEROOT points to the supplied source root directory. + # custom_generator: "CPPWG_SOURCEROOT/point_generator.py" + + # Custom C++ code to place at the top of the class wrapper. + # prefix_code: + - name: primitives source_locations: classes: - name: Shape - name: Cuboid - name: Rectangle + - name: mesh source_locations: classes: From 013f4f162881a972e93423e896d869711e39455b Mon Sep 17 00:00:00 2001 From: Kwabena N Amponsah Date: Fri, 3 May 2024 12:35:33 +0000 Subject: [PATCH 14/17] #4 implement exclude_default_args --- README.md | 2 +- cppwg/input/module_info.py | 4 +- cppwg/input/package_info.py | 3 ++ cppwg/parsers/package_info_parser.py | 4 ++ cppwg/writers/base_writer.py | 11 ----- cppwg/writers/constructor_writer.py | 58 ++++++++++++++------------- cppwg/writers/free_function_writer.py | 2 +- cppwg/writers/method_writer.py | 56 +++++++++++++------------- 8 files changed, 69 insertions(+), 71 deletions(-) diff --git a/README.md b/README.md index cc0c250..39562a0 100644 --- a/README.md +++ b/README.md @@ -52,7 +52,7 @@ Add a package description to `examples/shapes/wrapper/package_info.yaml`: name: pyshapes modules: - name: math_funcs - free_functions: cppwg_ALL + free_functions: CPPWG_ALL ``` Generate the wrappers with: diff --git a/cppwg/input/module_info.py b/cppwg/input/module_info.py index 0479315..ac2c792 100644 --- a/cppwg/input/module_info.py +++ b/cppwg/input/module_info.py @@ -3,8 +3,6 @@ import os from typing import Any, Dict, List, Optional -from pygccxml.declarations import declaration_t - from cppwg.input.base_info import BaseInfo @@ -54,7 +52,7 @@ def parent(self) -> "PackageInfo": # noqa: F821 """Returns the parent package info object.""" return self.package_info - def is_decl_in_source_path(self, decl: declaration_t) -> bool: + def is_decl_in_source_path(self, decl: "declaration_t") -> bool: # noqa: F821 """ Check if the declaration is associated with a file in the specified source paths. diff --git a/cppwg/input/package_info.py b/cppwg/input/package_info.py index 0a6c497..fdbe78c 100644 --- a/cppwg/input/package_info.py +++ b/cppwg/input/package_info.py @@ -25,6 +25,8 @@ class PackageInfo(BaseInfo): A list of source file names to include common_include_file : bool Use a common include file for all source files + exclude_default_args : bool + Exclude default arguments from method wrappers. """ def __init__( @@ -57,6 +59,7 @@ def __init__( self.source_hpp_patterns: List[str] = ["*.hpp"] self.source_hpp_files: List[str] = [] self.common_include_file: bool = False + self.exclude_default_args: bool = False if package_config: for key, value in package_config.items(): diff --git a/cppwg/parsers/package_info_parser.py b/cppwg/parsers/package_info_parser.py index 06cd6ca..f13b80e 100644 --- a/cppwg/parsers/package_info_parser.py +++ b/cppwg/parsers/package_info_parser.py @@ -133,6 +133,7 @@ def parse(self) -> PackageInfo: package_config: Dict[str, Any] = { "name": "cppwg_package", "common_include_file": True, + "exclude_default_args": False, "source_hpp_patterns": ["*.hpp"], } package_config.update(global_config) @@ -140,7 +141,10 @@ def parse(self) -> PackageInfo: for key in package_config.keys(): if key in self.raw_package_info: package_config[key] = self.raw_package_info[key] + + # Replace boolean strings with booleans utils.substitute_bool_for_string(package_config, "common_include_file") + utils.substitute_bool_for_string(package_config, "exclude_default_args") # Create the PackageInfo object from the package config dict self.package_info = PackageInfo( diff --git a/cppwg/writers/base_writer.py b/cppwg/writers/base_writer.py index 620dd5d..9bb4bd3 100644 --- a/cppwg/writers/base_writer.py +++ b/cppwg/writers/base_writer.py @@ -54,14 +54,3 @@ def tidy_name(self, name: str) -> str: return name - # TODO: This method is currently a placeholder. Consider implementing or removing. - def exclude_default_args(self) -> bool: - """ - Check if default arguments should be excluded from the wrapper code. - - Returns - ------- - bool - True if the default arguments should be excluded - """ - return False diff --git a/cppwg/writers/constructor_writer.py b/cppwg/writers/constructor_writer.py index 1ae240d..febbdd4 100644 --- a/cppwg/writers/constructor_writer.py +++ b/cppwg/writers/constructor_writer.py @@ -150,33 +150,35 @@ def generate_wrapper(self) -> str: wrapper_string += " >()" - # Default args e.g. py::arg("i") = 1 - default_args = "" - if not self.exclude_default_args(): - for arg in self.ctor_decl.arguments: - default_args += f', py::arg("{arg.name}")' - - if arg.default_value is not None: - default_value = str(arg.default_value) - - if self.template_params: - # Check for template params in default value - for param, val in zip(self.template_params, self.template_args): - if param in default_value: - # Replace e.g. Foo::DIM_A -> 2 - default_value = re.sub( - f"\\b{self.class_info.name}::{param}\\b", - str(val), - default_value, - ) - - # Replace e.g. -> <2> - default_value = re.sub( - f"\\b{param}\\b", f"{val}", default_value - ) - - default_args += f" = {default_value}" - - wrapper_string += default_args + ")\n" + # Keyword args with default values e.g. py::arg("i") = 1 + keyword_args = "" + for arg in self.ctor_decl.arguments: + keyword_args += f', py::arg("{arg.name}")' + + if not ( + arg.default_value is None + or self.class_info.hierarchy_attribute("exclude_default_args") + ): + default_value = str(arg.default_value) + + # Check for template params in default value + if self.template_params: + for param, val in zip(self.template_params, self.template_args): + if param in default_value: + # Replace e.g. Foo::DIM_A -> 2 + default_value = re.sub( + f"\\b{self.class_info.name}::{param}\\b", + str(val), + default_value, + ) + + # Replace e.g. -> <2> + default_value = re.sub( + f"\\b{param}\\b", f"{val}", default_value + ) + + keyword_args += f" = {default_value}" + + wrapper_string += keyword_args + ")\n" return wrapper_string diff --git a/cppwg/writers/free_function_writer.py b/cppwg/writers/free_function_writer.py index eb371ec..c3f29ac 100644 --- a/cppwg/writers/free_function_writer.py +++ b/cppwg/writers/free_function_writer.py @@ -48,7 +48,7 @@ def generate_wrapper(self) -> str: # e.g. without default values: ', py::arg("foo"), py::arg("bar")' # e.g. with default values: ', py::arg("foo") = 1, py::arg("bar") = 2' default_args = "" - if not self.exclude_default_args(): + if not self.free_function_info.hierarchy_attribute("exclude_default_args"): for argument in self.free_function_info.decls[0].arguments: default_args += f', py::arg("{argument.name}")' if argument.default_value is not None: diff --git a/cppwg/writers/method_writer.py b/cppwg/writers/method_writer.py index 69bc6bb..01a4cd2 100644 --- a/cppwg/writers/method_writer.py +++ b/cppwg/writers/method_writer.py @@ -142,32 +142,34 @@ def generate_wrapper(self) -> str: arg_types = [t.decl_string for t in self.method_decl.argument_types] arg_signature = ", ".join(arg_types) - # Default args e.g. py::arg("d") = 1.0 - default_args = "" - if not self.exclude_default_args(): - for arg in self.method_decl.arguments: - default_args += f', py::arg("{arg.name}")' - - if arg.default_value is not None: - default_value = str(arg.default_value) - - if self.template_params: - # Check for template params in default value - for param, val in zip(self.template_params, self.template_args): - if param in default_value: - # Replace e.g. Foo::DIM_A -> 2 - default_value = re.sub( - f"\\b{self.class_info.name}::{param}\\b", - str(val), - default_value, - ) - - # Replace e.g. -> <2> - default_value = re.sub( - f"\\b{param}\\b", f"{val}", default_value - ) - - default_args += f" = {default_value}" + # Keyword args with default values e.g. py::arg("i") = 1 + keyword_args = "" + for arg in self.method_decl.arguments: + keyword_args += f', py::arg("{arg.name}")' + + if not ( + arg.default_value is None + or self.class_info.hierarchy_attribute("exclude_default_args") + ): + default_value = str(arg.default_value) + + # Check for template params in default value + if self.template_params: + for param, val in zip(self.template_params, self.template_args): + if param in default_value: + # Replace e.g. Foo::DIM_A -> 2 + default_value = re.sub( + f"\\b{self.class_info.name}::{param}\\b", + str(val), + default_value, + ) + + # Replace e.g. -> <2> + default_value = re.sub( + f"\\b{param}\\b", f"{val}", default_value + ) + + keyword_args += f" = {default_value}" # Call policy, e.g. "py::return_value_policy::reference" call_policy = "" @@ -190,7 +192,7 @@ def generate_wrapper(self) -> str: "const_adorn": const_adorn, "class_short_name": self.class_short_name, "method_docs": '" "', - "default_args": default_args, + "default_args": keyword_args, "call_policy": call_policy, } class_method_template = self.wrapper_templates["class_method"] From ec7e741392a2061d8b3ed04c04221d1bead9cedc Mon Sep 17 00:00:00 2001 From: Kwabena N Amponsah Date: Fri, 3 May 2024 12:36:38 +0000 Subject: [PATCH 15/17] #4 update generated wrappers --- examples/shapes/src/geometry/Point.cpp | 16 +++++++++----- examples/shapes/src/geometry/Point.hpp | 5 +++++ .../shapes/wrapper/geometry/Point2.cppwg.cpp | 2 +- .../shapes/wrapper/geometry/Point3.cppwg.cpp | 2 +- examples/shapes/wrapper/package_info.yaml | 22 +++++++++++-------- .../wrapper/primitives/Shape2.cppwg.cpp | 2 +- .../wrapper/primitives/Shape3.cppwg.cpp | 2 +- 7 files changed, 33 insertions(+), 18 deletions(-) diff --git a/examples/shapes/src/geometry/Point.cpp b/examples/shapes/src/geometry/Point.cpp index 098b13d..87630e1 100644 --- a/examples/shapes/src/geometry/Point.cpp +++ b/examples/shapes/src/geometry/Point.cpp @@ -8,12 +8,12 @@ Point::Point() template Point::Point(double x, double y, double z) - : mIndex(0) - , mLocation() + : mIndex(0), mLocation() { mLocation[0] = x; mLocation[1] = y; - if (DIM == 3) { + if (DIM == 3) + { mLocation[2] = z; } } @@ -30,7 +30,7 @@ std::array Point::GetLocation() const } template -const std::array& Point::rGetLocation() const +const std::array &Point::rGetLocation() const { return mLocation; } @@ -48,10 +48,16 @@ void Point::SetIndex(unsigned index) } template -void Point::SetLocation(const std::array& rLocation) +void Point::SetLocation(const std::array &rLocation) { mLocation = rLocation; } +template +void Point::ExcludedMethod() +{ + // Excluded method +} + template class Point<2>; template class Point<3>; diff --git a/examples/shapes/src/geometry/Point.hpp b/examples/shapes/src/geometry/Point.hpp index 5ffb56f..fe93805 100644 --- a/examples/shapes/src/geometry/Point.hpp +++ b/examples/shapes/src/geometry/Point.hpp @@ -60,6 +60,11 @@ class Point * Set the location */ void SetLocation(const std::array &rLocation); + + /** + * Placeholder method to exclude from wrapping + */ + void ExcludedMethod(); }; #endif // _POINT_HPP diff --git a/examples/shapes/wrapper/geometry/Point2.cppwg.cpp b/examples/shapes/wrapper/geometry/Point2.cppwg.cpp index 12b69e7..6ca7333 100644 --- a/examples/shapes/wrapper/geometry/Point2.cppwg.cpp +++ b/examples/shapes/wrapper/geometry/Point2.cppwg.cpp @@ -19,7 +19,7 @@ py::class_ >(m, "Point2") .def( "rGetLocation", (::std::array const &(Point2::*)() const ) &Point2::rGetLocation, - " " ) + " " , py::return_value_policy::reference_internal) .def( "GetIndex", (unsigned int(Point2::*)() const ) &Point2::GetIndex, diff --git a/examples/shapes/wrapper/geometry/Point3.cppwg.cpp b/examples/shapes/wrapper/geometry/Point3.cppwg.cpp index 04f277f..b489ecb 100644 --- a/examples/shapes/wrapper/geometry/Point3.cppwg.cpp +++ b/examples/shapes/wrapper/geometry/Point3.cppwg.cpp @@ -19,7 +19,7 @@ py::class_ >(m, "Point3") .def( "rGetLocation", (::std::array const &(Point3::*)() const ) &Point3::rGetLocation, - " " ) + " " , py::return_value_policy::reference_internal) .def( "GetIndex", (unsigned int(Point3::*)() const ) &Point3::GetIndex, diff --git a/examples/shapes/wrapper/package_info.yaml b/examples/shapes/wrapper/package_info.yaml index 237762d..51efc20 100644 --- a/examples/shapes/wrapper/package_info.yaml +++ b/examples/shapes/wrapper/package_info.yaml @@ -7,15 +7,23 @@ pointer_call_policy: reference # Default value of pybind11::return_value_policy for references. reference_call_policy: reference_internal -# Set True to include the common include file (all headers) in all wrappers. -common_include_file: False -# Headers to be included in all wrappers. +# Set False to not include the common include file (all headers) in all wrappers. +common_include_file: True +# Headers to include in all wrappers. source_includes: - -# Exclude default arguments from method signatures. +# Exclude default arguments from wrapped methods. exclude_default_args: False +# Exclude any methods that have these arg types. +# arg_type_excludes: +# - double + +# Exclude any constructors that have these arg types. +# constructor_arg_type_excludes: +# - double + # Signature/replacement settings for explicit template instantiations. template_substitutions: - signature: @@ -45,11 +53,7 @@ modules: excluded_methods: - ExcludedMethod - # Exclude any constructors that have these arg types. - # constructor_arg_type_excludes: - # - double - - # Path to custom script for generating wrappers for this class. + # Path to a custom script for generating wrappers for this class. # CPPWG_SOURCEROOT points to the supplied source root directory. # custom_generator: "CPPWG_SOURCEROOT/point_generator.py" diff --git a/examples/shapes/wrapper/primitives/Shape2.cppwg.cpp b/examples/shapes/wrapper/primitives/Shape2.cppwg.cpp index cfb6a0d..4bb1651 100644 --- a/examples/shapes/wrapper/primitives/Shape2.cppwg.cpp +++ b/examples/shapes/wrapper/primitives/Shape2.cppwg.cpp @@ -18,7 +18,7 @@ py::class_ >(m, "Shape2") .def( "rGetVertices", (::std::vector>> const &(Shape2::*)() const ) &Shape2::rGetVertices, - " " ) + " " , py::return_value_policy::reference_internal) .def( "SetIndex", (void(Shape2::*)(unsigned int)) &Shape2::SetIndex, diff --git a/examples/shapes/wrapper/primitives/Shape3.cppwg.cpp b/examples/shapes/wrapper/primitives/Shape3.cppwg.cpp index cb81bf3..a43674f 100644 --- a/examples/shapes/wrapper/primitives/Shape3.cppwg.cpp +++ b/examples/shapes/wrapper/primitives/Shape3.cppwg.cpp @@ -18,7 +18,7 @@ py::class_ >(m, "Shape3") .def( "rGetVertices", (::std::vector>> const &(Shape3::*)() const ) &Shape3::rGetVertices, - " " ) + " " , py::return_value_policy::reference_internal) .def( "SetIndex", (void(Shape3::*)(unsigned int)) &Shape3::SetIndex, From f7e7cfe9e6538ec1bf387710d8e4541b0236a3fa Mon Sep 17 00:00:00 2001 From: Kwabena N Amponsah Date: Fri, 3 May 2024 13:09:43 +0000 Subject: [PATCH 16/17] #4 rename short_name and full_name to py_name and cpp_name --- cppwg/generators.py | 4 +- cppwg/input/class_info.py | 36 ++++++------ cppwg/parsers/package_info_parser.py | 2 +- cppwg/templates/pybind11_default.py | 28 ++++----- cppwg/writers/base_writer.py | 1 - cppwg/writers/class_writer.py | 72 ++++++++++++----------- cppwg/writers/constructor_writer.py | 10 ++-- cppwg/writers/header_collection_writer.py | 14 ++--- cppwg/writers/method_writer.py | 16 ++--- cppwg/writers/module_writer.py | 8 +-- 10 files changed, 96 insertions(+), 95 deletions(-) diff --git a/cppwg/generators.py b/cppwg/generators.py index c7c62f5..b8e04aa 100644 --- a/cppwg/generators.py +++ b/cppwg/generators.py @@ -278,8 +278,8 @@ def add_class_decls(self) -> None: for class_info in module_info.class_info_collection: class_info.decls: List["class_t"] = [] # noqa: F821 - for full_name in class_info.full_names: - decl_name = full_name.replace(" ", "") # e.g. Foo<2,2> + for class_cpp_name in class_info.cpp_names: + decl_name = class_cpp_name.replace(" ", "") # e.g. Foo<2,2> try: class_decl = self.source_ns.class_(decl_name) diff --git a/cppwg/input/class_info.py b/cppwg/input/class_info.py index 8622c29..af4c566 100644 --- a/cppwg/input/class_info.py +++ b/cppwg/input/class_info.py @@ -11,9 +11,9 @@ class CppClassInfo(CppTypeInfo): Attributes ---------- - full_names : List[str] + cpp_names : List[str] The C++ names of the class e.g. ["Foo<2,2>", "Foo<3,3>"] - short_names : List[str] + py_names : List[str] The Python names of the class e.g. ["Foo2_2", "Foo3_3"] """ @@ -21,10 +21,10 @@ def __init__(self, name: str, class_config: Optional[Dict[str, Any]] = None): super(CppClassInfo, self).__init__(name, class_config) - self.full_names: List[str] = None - self.short_names: List[str] = None + self.cpp_names: List[str] = None + self.py_names: List[str] = None - def update_short_names(self) -> None: + def update_py_names(self) -> None: """ Set the Python names for the class, accounting for template args. @@ -32,18 +32,18 @@ def update_short_names(self) -> None: collapses template arguments, separating them by underscores and removes special characters. The return type is a list, as a class can have multiple names if it is templated. For example, a class "Foo" with - template arguments [[2, 2], [3, 3]] will have a short name list + template arguments [[2, 2], [3, 3]] will have a python name list ["Foo2_2", "Foo3_3"]. """ # Handles untemplated classes if self.template_arg_lists is None: if self.name_override: - self.short_names = [self.name_override] + self.py_names = [self.name_override] else: - self.short_names = [self.name] + self.py_names = [self.name] return - self.short_names = [] + self.py_names = [] # Table of special characters for removal rm_chars = {"<": None, ">": None, ",": None, " ": None} @@ -89,36 +89,36 @@ def update_short_names(self) -> None: if idx < len(template_arg_list) - 1: template_string += "_" - self.short_names.append(type_name + template_string) + self.py_names.append(type_name + template_string) - def update_full_names(self) -> None: + def update_cpp_names(self) -> None: """ Set the C++ names for the class, accounting for template args. Set the name of the class as it should appear in C++. The return type is a list, as a class can have multiple names if it is templated. For example, a class "Foo" with - template arguments [[2, 2], [3, 3]] will have a full name list + template arguments [[2, 2], [3, 3]] will have a C++ name list ["Foo<2,2 >", "Foo<3,3 >"]. """ # Handles untemplated classes if self.template_arg_lists is None: - self.full_names = [self.name] + self.cpp_names = [self.name] return - self.full_names = [] + self.cpp_names = [] for template_arg_list in self.template_arg_lists: # Create template string from arg list e.g. [2, 2] -> "<2,2 >" template_string = ",".join([str(arg) for arg in template_arg_list]) template_string = "<" + template_string + " >" # Join full name e.g. "Foo<2,2 >" - self.full_names.append(self.name + template_string) + self.cpp_names.append(self.name + template_string) def update_names(self) -> None: - """Update the full and short names for the class.""" - self.update_full_names() - self.update_short_names() + """Update the C++ and Python names for the class.""" + self.update_cpp_names() + self.update_py_names() @property def parent(self) -> "ModuleInfo": # noqa: F821 diff --git a/cppwg/parsers/package_info_parser.py b/cppwg/parsers/package_info_parser.py index f13b80e..552c404 100644 --- a/cppwg/parsers/package_info_parser.py +++ b/cppwg/parsers/package_info_parser.py @@ -141,7 +141,7 @@ def parse(self) -> PackageInfo: for key in package_config.keys(): if key in self.raw_package_info: package_config[key] = self.raw_package_info[key] - + # Replace boolean strings with booleans utils.substitute_bool_for_string(package_config, "common_include_file") utils.substitute_bool_for_string(package_config, "exclude_default_args") diff --git a/cppwg/templates/pybind11_default.py b/cppwg/templates/pybind11_default.py index b4dfd26..010fe67 100644 --- a/cppwg/templates/pybind11_default.py +++ b/cppwg/templates/pybind11_default.py @@ -4,10 +4,10 @@ #include #include {includes} -#include "{class_short_name}.%s.hpp" +#include "{class_py_name}.%s.hpp" namespace py = pybind11; -typedef {class_full_name} {class_short_name}; +typedef {class_cpp_name} {class_py_name}; {smart_ptr_handle}; """ % CPPWG_EXT @@ -16,43 +16,43 @@ #include {includes} //#include "PythonObjectConverters.hpp" -#include "{class_short_name}.%s.hpp" +#include "{class_py_name}.%s.hpp" namespace py = pybind11; //PYBIND11_CVECTOR_TYPECASTER2(); //PYBIND11_CVECTOR_TYPECASTER3(); -typedef {class_full_name} {class_short_name}; +typedef {class_cpp_name} {class_py_name}; {smart_ptr_handle}; """ % CPPWG_EXT class_hpp_header = """\ -#ifndef {class_short_name}_hpp__%s_wrapper -#define {class_short_name}_hpp__%s_wrapper +#ifndef {class_py_name}_hpp__%s_wrapper +#define {class_py_name}_hpp__%s_wrapper #include -void register_{class_short_name}_class(pybind11::module &m); -#endif // {class_short_name}_hpp__%s_wrapper +void register_{class_py_name}_class(pybind11::module &m); +#endif // {class_py_name}_hpp__%s_wrapper """ % tuple([CPPWG_EXT]*3) class_virtual_override_header = """\ -class {class_short_name}%s : public {class_short_name}{{ +class {class_py_name}%s : public {class_py_name}{{ public: - using {class_short_name}::{class_base_name}; + using {class_py_name}::{class_base_name}; """ % CPPWG_CLASS_OVERRIDE_SUFFIX class_virtual_override_footer = "}\n" class_definition = """\ -void register_{short_name}_class(py::module &m){{ -py::class_<{short_name} {overrides_string} {ptr_support} {bases} >(m, "{short_name}") +void register_{class_py_name}_class(py::module &m){{ +py::class_<{class_py_name} {overrides_string} {ptr_support} {bases} >(m, "{class_py_name}") """ method_virtual_override = """\ {return_type} {method_name}({arg_string}){const_adorn} override {{ PYBIND11_OVERRIDE{overload_adorn}( {tidy_method_name}, - {short_class_name}, + {class_py_name}, {method_name}, {args_string}); }} @@ -67,7 +67,7 @@ class {class_short_name}%s : public {class_short_name}{{ class_method = """\ .def{def_adorn}( "{method_name}", - ({return_type}({self_ptr})({arg_signature}){const_adorn}) &{class_short_name}::{method_name}, + ({return_type}({self_ptr})({arg_signature}){const_adorn}) &{class_py_name}::{method_name}, {method_docs} {default_args} {call_policy}) """ diff --git a/cppwg/writers/base_writer.py b/cppwg/writers/base_writer.py index 9bb4bd3..ca2f3cd 100644 --- a/cppwg/writers/base_writer.py +++ b/cppwg/writers/base_writer.py @@ -53,4 +53,3 @@ def tidy_name(self, name: str) -> str: name = name.replace(key, value) return name - diff --git a/cppwg/writers/class_writer.py b/cppwg/writers/class_writer.py index fa97619..68c8bb1 100644 --- a/cppwg/writers/class_writer.py +++ b/cppwg/writers/class_writer.py @@ -50,8 +50,8 @@ def __init__( self.class_info: "CppClassInfo" = class_info # noqa: F821 - if len(self.class_info.full_names) != len(self.class_info.short_names): - logger.error("Full and short name lists should be the same length") + if len(self.class_info.cpp_names) != len(self.class_info.py_names): + logger.error("C++ and Python class name lists should be the same length") raise AssertionError() self.module_class_decls: List["class_t"] = module_class_decls # noqa: F821 @@ -62,31 +62,31 @@ def __init__( self.hpp_string: str = "" self.cpp_string: str = "" - def add_hpp(self, class_short_name: str) -> None: + def add_hpp(self, class_py_name: str) -> None: """ Fill the class hpp string for a single class using the wrapper template. Parameters ---------- - class_short_name: str - The short name of the class e.g. Foo2_2 + class_py_name: str + The Python name of the class e.g. Foo2_2 """ - class_hpp_dict = {"class_short_name": class_short_name} + class_hpp_dict = {"class_py_name": class_py_name} self.hpp_string += self.wrapper_templates["class_hpp_header"].format( **class_hpp_dict ) - def add_cpp_header(self, class_full_name: str, class_short_name: str) -> None: + def add_cpp_header(self, class_cpp_name: str, class_py_name: str) -> None: """ Add the 'top' of the class wrapper cpp file for a single class. Parameters ---------- - class_full_name : str - The full name of the class e.g. Foo<2,2> - class_short_name : str - The short name of the class e.g. Foo2_2 + class_cpp_name : str + The C++ name of the class e.g. Foo<2,2> + class_py_name : str + The Python name of the class e.g. Foo2_2 """ # Add the includes for this class includes = "" @@ -127,8 +127,8 @@ def add_cpp_header(self, class_full_name: str, class_short_name: str) -> None: # Fill in the cpp header template header_dict = { "includes": includes, - "class_short_name": class_short_name, - "class_full_name": class_full_name, + "class_py_name": class_py_name, + "class_cpp_name": class_cpp_name, "smart_ptr_handle": smart_ptr_handle, } @@ -143,7 +143,7 @@ def add_cpp_header(self, class_full_name: str, class_short_name: str) -> None: # Run any custom generators to add additional prefix code if self.class_info.custom_generator: self.cpp_string += self.class_info.custom_generator.get_class_cpp_pre_code( - class_short_name + class_py_name ) def add_virtual_overrides( @@ -183,23 +183,23 @@ def add_virtual_overrides( # e.g. typedef ::Bar<2> * _Bar_lt_2_gt_Ptr; for return_type in return_types: if return_type != self.tidy_name(return_type): - typedef_template = "typedef {full_name} {tidy_name};\n" + typedef_template = "typedef {class_cpp_name} {tidy_name};\n" typedef_dict = { - "full_name": return_type, + "class_cpp_name": return_type, "tidy_name": self.tidy_name(return_type), } self.cpp_string += typedef_template.format(**typedef_dict) self.cpp_string += "\n" # Override virtual methods - short_name = self.class_info.short_names[template_idx] + class_py_name = self.class_info.py_names[template_idx] if methods_needing_override: # Add virtual override class, e.g.: # class Foo_Overrides : public Foo { # public: # using Foo::Foo; override_header_dict = { - "class_short_name": short_name, + "class_py_name": class_py_name, "class_base_name": self.class_info.name, } @@ -239,18 +239,18 @@ def write(self, work_dir: str) -> None: """ logger = logging.getLogger() - if len(self.class_info.decls) != len(self.class_info.full_names): + if len(self.class_info.decls) != len(self.class_info.cpp_names): logger.error("Not enough class decls added to do write.") raise AssertionError() - for idx, full_name in enumerate(self.class_info.full_names): - short_name = self.class_info.short_names[idx] + for idx, class_cpp_name in enumerate(self.class_info.cpp_names): + class_py_name = self.class_info.py_names[idx] class_decl = self.class_info.decls[idx] self.hpp_string = "" self.cpp_string = "" # Add the cpp file header - self.add_cpp_header(full_name, short_name) + self.add_cpp_header(class_cpp_name, class_py_name) # Check for struct-enum pattern. For example: # struct Foo{ @@ -276,10 +276,10 @@ def write(self, work_dir: str) -> None: self.cpp_string += " .export_values();\n}\n" # Set up the hpp - self.add_hpp(short_name) + self.add_hpp(class_py_name) # Write the struct cpp and hpp files - self.write_files(work_dir, short_name) + self.write_files(work_dir, class_py_name) continue # Find and define virtual function "trampoline" overrides @@ -292,14 +292,14 @@ def write(self, work_dir: str) -> None: # e.g. py::class_(m, "Foo") overrides_string = "" if methods_needing_override: - overrides_string = f", {short_name}{CPPWG_CLASS_OVERRIDE_SUFFIX}" + overrides_string = f", {class_py_name}{CPPWG_CLASS_OVERRIDE_SUFFIX}" # Add smart pointer support to the wrapper class definition if needed # e.g. py::class_ >(m, "Foo") smart_ptr_type: str = self.class_info.hierarchy_attribute("smart_ptr_type") ptr_support = "" if self.has_shared_ptr and smart_ptr_type: - ptr_support = f", {smart_ptr_type}<{short_name} > " + ptr_support = f", {smart_ptr_type}<{class_py_name} > " # Add base classes to the wrapper class definition if needed # e.g. py::class_(m, "Foo") @@ -316,7 +316,7 @@ def write(self, work_dir: str) -> None: # Add the class registration class_definition_dict = { - "short_name": short_name, + "class_py_name": class_py_name, "overrides_string": overrides_string, "ptr_support": ptr_support, "bases": bases, @@ -358,19 +358,21 @@ def write(self, work_dir: str) -> None: # Run any custom generators to add additional class code if self.class_info.custom_generator: self.cpp_string += ( - self.class_info.custom_generator.get_class_cpp_def_code(short_name) + self.class_info.custom_generator.get_class_cpp_def_code( + class_py_name + ) ) # Close the class definition self.cpp_string += " ;\n}\n" # Set up the hpp - self.add_hpp(short_name) + self.add_hpp(class_py_name) # Write the class cpp and hpp files - self.write_files(work_dir, short_name) + self.write_files(work_dir, class_py_name) - def write_files(self, work_dir: str, class_short_name: str) -> None: + def write_files(self, work_dir: str, class_py_name: str) -> None: """ Write the hpp and cpp wrapper code to file. @@ -378,11 +380,11 @@ def write_files(self, work_dir: str, class_short_name: str) -> None: ---------- work_dir : str The directory to write the files to - class_short_name : str - The short name of the class e.g. Foo2_2 + class_py_name : str + The Python name of the class e.g. Foo2_2 """ - hpp_filepath = os.path.join(work_dir, f"{class_short_name}.{CPPWG_EXT}.hpp") - cpp_filepath = os.path.join(work_dir, f"{class_short_name}.{CPPWG_EXT}.cpp") + hpp_filepath = os.path.join(work_dir, f"{class_py_name}.{CPPWG_EXT}.hpp") + cpp_filepath = os.path.join(work_dir, f"{class_py_name}.{CPPWG_EXT}.cpp") with open(hpp_filepath, "w") as hpp_file: hpp_file.write(self.hpp_string) diff --git a/cppwg/writers/constructor_writer.py b/cppwg/writers/constructor_writer.py index febbdd4..dde6bd8 100644 --- a/cppwg/writers/constructor_writer.py +++ b/cppwg/writers/constructor_writer.py @@ -24,8 +24,8 @@ class CppConstructorWrapperWriter(CppBaseWrapperWriter): The class declaration for the class containing the constructor wrapper_templates : Dict[str, str] String templates with placeholders for generating wrapper code - class_short_name : Optional[str] - The short name of the class e.g. 'Foo2_2' + class_py_name : Optional[str] + The Python name of the class e.g. 'Foo2_2' template_params: Optional[List[str]] The template params for the class e.g. ['DIM_A', 'DIM_B'] template_args: Optional[List[str]] @@ -46,9 +46,9 @@ def __init__( self.ctor_decl: "constructor_t" = ctor_decl # noqa: F821 self.class_decl: "class_t" = class_info.decls[template_idx] # noqa: F821 - self.class_short_name = class_info.short_names[template_idx] - if self.class_short_name is None: - self.class_short_name = self.class_decl.name + self.class_py_name = class_info.py_names[template_idx] + if self.class_py_name is None: + self.class_py_name = self.class_decl.name self.template_params = class_info.template_params diff --git a/cppwg/writers/header_collection_writer.py b/cppwg/writers/header_collection_writer.py index 0be1660..ca9df41 100644 --- a/cppwg/writers/header_collection_writer.py +++ b/cppwg/writers/header_collection_writer.py @@ -129,15 +129,15 @@ def write(self) -> None: if not class_info.template_arg_lists: continue - # Class full names eg. ["Foo<2,2>", "Foo<3,3>"] - full_names = [name.replace(" ", "") for name in class_info.full_names] + # C++ class names eg. ["Foo<2,2>", "Foo<3,3>"] + cpp_names = [name.replace(" ", "") for name in class_info.cpp_names] - # Class short names eg. ["Foo2_2", "Foo3_3"] - short_names = [name.replace(" ", "") for name in class_info.short_names] + # Python class names eg. ["Foo2_2", "Foo3_3"] + py_names = [name.replace(" ", "") for name in class_info.py_names] - for full_name, short_name in zip(full_names, short_names): - template_instantiations += f"template class {full_name};\n" - template_typedefs += f"typedef {full_name} {short_name};\n" + for cpp_name, py_name in zip(cpp_names, py_names): + template_instantiations += f"template class {cpp_name};\n" + template_typedefs += f"typedef {cpp_name} {py_name};\n" self.hpp_collection_string += "\n// Instantiate Template Classes\n" self.hpp_collection_string += template_instantiations diff --git a/cppwg/writers/method_writer.py b/cppwg/writers/method_writer.py index 01a4cd2..3d4d621 100644 --- a/cppwg/writers/method_writer.py +++ b/cppwg/writers/method_writer.py @@ -24,8 +24,8 @@ class CppMethodWrapperWriter(CppBaseWrapperWriter): The class declaration for the class containing the method wrapper_templates : Dict[str, str] String templates with placeholders for generating wrapper code - class_short_name : Optional[str] - The short name of the class e.g. 'Foo2_2' + class_py_name : Optional[str] + The Python name of the class e.g. 'Foo2_2' template_params: Optional[List[str]] The template params for the class e.g. ['DIM_A', 'DIM_B'] template_args: Optional[List[str]] @@ -46,9 +46,9 @@ def __init__( self.method_decl: "member_function_t" = method_decl # noqa: F821 self.class_decl: "class_t" = class_info.decls[template_idx] # noqa: F821 - self.class_short_name = class_info.short_names[template_idx] - if self.class_short_name is None: - self.class_short_name = self.class_decl.name + self.class_py_name = class_info.py_names[template_idx] + if self.class_py_name is None: + self.class_py_name = self.class_decl.name self.template_params = class_info.template_params @@ -131,7 +131,7 @@ def generate_wrapper(self) -> str: self_ptr = "*" else: # e.g. Foo2_2::* - self_ptr = self.class_short_name + "::*" + self_ptr = self.class_py_name + "::*" # Const-ness const_adorn = "" @@ -190,7 +190,7 @@ def generate_wrapper(self) -> str: "self_ptr": self_ptr, "arg_signature": arg_signature, "const_adorn": const_adorn, - "class_short_name": self.class_short_name, + "class_py_name": self.class_py_name, "method_docs": '" "', "default_args": keyword_args, "call_policy": call_policy, @@ -258,7 +258,7 @@ def generate_virtual_override_wrapper(self) -> str: "const_adorn": const_adorn, "overload_adorn": overload_adorn, "tidy_method_name": self.tidy_name(return_string), - "short_class_name": self.class_short_name, + "class_py_name": self.class_py_name, "args_string": arg_name_string, } wrapper_string = self.wrapper_templates["method_virtual_override"].format( diff --git a/cppwg/writers/module_writer.py b/cppwg/writers/module_writer.py index a4abc9f..6f726c0 100644 --- a/cppwg/writers/module_writer.py +++ b/cppwg/writers/module_writer.py @@ -83,9 +83,9 @@ def write_module_wrapper(self) -> None: # Add includes for class wrappers in the module for class_info in self.module_info.class_info_collection: - for short_name in class_info.short_names: + for py_name in class_info.py_names: # Example: #include "Foo2_2.cppwg.hpp" - cpp_string += f'#include "{short_name}.{CPPWG_EXT}.hpp"\n' + cpp_string += f'#include "{py_name}.{CPPWG_EXT}.hpp"\n' # Format module name as _packagename_modulename full_module_name = ( @@ -106,9 +106,9 @@ def write_module_wrapper(self) -> None: # Add classes for class_info in self.module_info.class_info_collection: - for short_name in class_info.short_names: + for py_name in class_info.py_names: # Example: register_Foo2_2_class(m);" - cpp_string += f" register_{short_name}_class(m);\n" + cpp_string += f" register_{py_name}_class(m);\n" # Add code from the module's custom generator if self.module_info.custom_generator: From cfe52737e566c6a47470f58d45be63f517fab2d5 Mon Sep 17 00:00:00 2001 From: Kwabena N Amponsah Date: Fri, 3 May 2024 13:14:12 +0000 Subject: [PATCH 17/17] #4 fix remaining todos --- cppwg/input/cpp_type_info.py | 23 ----------------------- cppwg/writers/class_writer.py | 6 ------ cppwg/writers/module_writer.py | 4 +--- 3 files changed, 1 insertion(+), 32 deletions(-) diff --git a/cppwg/input/cpp_type_info.py b/cppwg/input/cpp_type_info.py index fcd166d..3260d85 100644 --- a/cppwg/input/cpp_type_info.py +++ b/cppwg/input/cpp_type_info.py @@ -45,26 +45,3 @@ def __init__(self, name: str, type_config: Optional[Dict[str, Any]] = None): if type_config: for key, value in type_config.items(): setattr(self, key, value) - - # TODO: This method is not used, remove it? - def needs_header_file_instantiation(self): - """Check if this class needs to be instantiated in the header file.""" - return ( - (self.template_arg_lists is not None) - and (not self.include_file_only) - and (self.needs_instantiation) - ) - - # TODO: This method is not used, remove it? - def needs_header_file_typdef(self): - """ - Check if this type need to be typdef'd with a nicer name. - - The typedefs are declared in the header file. All template classes need this. - """ - return (self.template_arg_lists is not None) and (not self.include_file_only) - - # TODO: This method is not used, remove it? - def needs_auto_wrapper_generation(self): - """Check if this class needs a wrapper to be autogenerated.""" - return not self.include_file_only diff --git a/cppwg/writers/class_writer.py b/cppwg/writers/class_writer.py index 68c8bb1..0f1fbba 100644 --- a/cppwg/writers/class_writer.py +++ b/cppwg/writers/class_writer.py @@ -30,8 +30,6 @@ class CppClassWrapperWriter(CppBaseWrapperWriter): A list of decls for all classes in the module has_shared_ptr : bool Whether the class uses shared pointers - is_abstract : bool - Whether the class is abstract hpp_string : str The hpp wrapper code cpp_string : str @@ -57,7 +55,6 @@ def __init__( self.module_class_decls: List["class_t"] = module_class_decls # noqa: F821 self.has_shared_ptr: bool = True - self.is_abstract: bool = False # TODO: Consider removing unused attribute self.hpp_string: str = "" self.cpp_string: str = "" @@ -176,8 +173,6 @@ def add_virtual_overrides( if is_pure_virtual or is_virtual: methods_needing_override.append(member_function) return_types.append(member_function.return_type.decl_string) - if is_pure_virtual: - self.is_abstract = True # Add typedefs for return types with special characters # e.g. typedef ::Bar<2> * _Bar_lt_2_gt_Ptr; @@ -256,7 +251,6 @@ def write(self, work_dir: str) -> None: # struct Foo{ # enum Value{A, B, C}; # }; - # TODO: Consider moving some parts into templates if declarations.is_struct(class_decl): enums = class_decl.enumerations(allow_empty=True) diff --git a/cppwg/writers/module_writer.py b/cppwg/writers/module_writer.py index 6f726c0..65e2189 100644 --- a/cppwg/writers/module_writer.py +++ b/cppwg/writers/module_writer.py @@ -42,9 +42,7 @@ def __init__( self.module_info: "ModuleInfo" = module_info # noqa: F821 self.wrapper_templates: Dict[str, str] = wrapper_templates self.wrapper_root: str = wrapper_root - self.package_license: str = ( - package_license # TODO: use this in the generated wrappers - ) + self.package_license: str = package_license # For convenience, store a list of declarations of all # classes to be wrapped in the module