diff --git a/robotpy_build/autowrap/cxxparser.py b/robotpy_build/autowrap/cxxparser.py index 3603a797..978dc053 100644 --- a/robotpy_build/autowrap/cxxparser.py +++ b/robotpy_build/autowrap/cxxparser.py @@ -1072,6 +1072,9 @@ def _on_class_method( # Update class-specific method attributes fctx.is_constructor = is_constructor + if is_constructor and method_data.rename and not method_data.cpp_code: + fctx.cpp_return_type = cctx.full_cpp_name + self._on_fn_make_lambda(method_data, fctx) if operator: fctx.operator = operator self.hctx.need_operators_h = True @@ -1581,6 +1584,7 @@ def _on_fn_make_lambda(self, data: FunctionData, fctx: FunctionContext): * When an 'out' parameter is detected (a pointer receiving a value) * When a buffer + size parameter exists (either in or out) + * When "renaming" a constructor overload to a static method """ # Statements to insert before calling the function diff --git a/robotpy_build/autowrap/render_pybind11.py b/robotpy_build/autowrap/render_pybind11.py index 66bfb49c..bdc5df04 100644 --- a/robotpy_build/autowrap/render_pybind11.py +++ b/robotpy_build/autowrap/render_pybind11.py @@ -7,6 +7,7 @@ Documentation, EnumContext, FunctionContext, + GeneratedLambda, PropContext, ) @@ -67,6 +68,22 @@ def _genmethod( elif fn.is_constructor: if fn.cpp_code: r.writeln(f".def(py::init({fn.cpp_code})") + elif fn.genlambda: + genlambda = fn.genlambda + arg_params = genlambda.in_params + lam_params = [param.decl for param in arg_params] + # TODO: trampoline + assert cls_qualname is not None + call_qual = cls_qualname + _gen_method_lambda( + r, + fn, + genlambda, + call_qual, + tmpl, + f'.def_static("{fn.py_name}"', + lam_params, + ) elif trampoline_qualname: r.writeln( f".def(py::init_alias<{', '.join(param.full_cpp_type for param in arg_params)}>()" @@ -93,29 +110,14 @@ def _genmethod( if cls_qualname: lam_params = [f"{cls_qualname} &self"] + lam_params - r.writeln(f"{fn_def}, []({', '.join(lam_params)}) {{") - - with r.indent(): - if genlambda.pre: - r.writeln(genlambda.pre) - - if trampoline_qualname: - call_qual = f"(({trampoline_qualname}*)&self)->" - elif cls_qualname: - call_qual = f"(({cls_qualname}*)&self)->" - else: - call_qual = f"{fn.namespace}::" - - call_params = ", ".join(p.call_name for p in fn.all_params) - - r.writeln( - f"{genlambda.call_start}{call_qual}{fn.cpp_name}{tmpl}({call_params});" - ) - - if genlambda.ret: - r.writeln(genlambda.ret) + if trampoline_qualname: + call_qual = f"(({trampoline_qualname}*)&self)->{fn.cpp_name}" + elif cls_qualname: + call_qual = f"(({cls_qualname}*)&self)->{fn.cpp_name}" + else: + call_qual = f"{fn.namespace}::{fn.cpp_name}" - r.writeln("}") + _gen_method_lambda(r, fn, genlambda, call_qual, tmpl, fn_def, lam_params) else: if trampoline_qualname: @@ -172,6 +174,31 @@ def _genmethod( r.writeln(f"#endif // {fn.ifndef}\n") +def _gen_method_lambda( + r: RenderBuffer, + fn: FunctionContext, + genlambda: GeneratedLambda, + call_qual: str, + tmpl: str, + fn_def: str, + lam_params: T.List[str], +): + r.writeln(f"{fn_def}, []({', '.join(lam_params)}) {{") + + with r.indent(): + if genlambda.pre: + r.writeln(genlambda.pre) + + call_params = ", ".join(p.call_name for p in fn.all_params) + + r.writeln(f"{genlambda.call_start}{call_qual}{tmpl}({call_params});") + + if genlambda.ret: + r.writeln(genlambda.ret) + + r.writeln("}") + + def genmethod( r: RenderBuffer, cls_qualname: T.Optional[str], diff --git a/tests/cpp/gen/ft/rename.yml b/tests/cpp/gen/ft/rename.yml index 922fb94a..687ba99e 100644 --- a/tests/cpp/gen/ft/rename.yml +++ b/tests/cpp/gen/ft/rename.yml @@ -26,10 +26,15 @@ classes: Param1: rename: P1 methods: + OriginalClass: + overloads: + '': + int: + rename: new fnOriginal: rename: fnRenamed fnRenamedParam: param_override: x: name: y - setProp: \ No newline at end of file + setProp: diff --git a/tests/cpp/rpytest/ft/include/rename.h b/tests/cpp/rpytest/ft/include/rename.h index c1e5db28..0f5a1f82 100644 --- a/tests/cpp/rpytest/ft/include/rename.h +++ b/tests/cpp/rpytest/ft/include/rename.h @@ -12,6 +12,9 @@ int fnRenamedParam(int x) { return x; } // class struct OriginalClass { + // constructor + OriginalClass() = default; + explicit OriginalClass(int prop) : originalProp(prop) {}; // class function int fnOriginal() { return 0x2; } @@ -37,4 +40,4 @@ struct OriginalClass { // enums enum OriginalEnum { Original1 = 1 -}; \ No newline at end of file +}; diff --git a/tests/test_ft_rename.py b/tests/test_ft_rename.py index 29237db2..250b6305 100644 --- a/tests/test_ft_rename.py +++ b/tests/test_ft_rename.py @@ -30,6 +30,10 @@ def test_rename_cls(): assert not hasattr(c.ClassRenamedEnum, "Param1") assert c.ClassRenamedEnum.P1 == 1 + n = ft.RenamedClass.new(1) + assert isinstance(n, ft.RenamedClass) + assert n.renamedProp == 1 + def test_rename_enums(): assert not hasattr(ft._rpytest_ft, "OriginalEnum")