Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions robotpy_build/autowrap/cxxparser.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
71 changes: 49 additions & 22 deletions robotpy_build/autowrap/render_pybind11.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
Documentation,
EnumContext,
FunctionContext,
GeneratedLambda,
PropContext,
)

Expand Down Expand Up @@ -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)}>()"
Expand All @@ -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:
Expand Down Expand Up @@ -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],
Expand Down
6 changes: 5 additions & 1 deletion robotpy_build/config/autowrap_yml.py
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,8 @@ class FunctionData(Model):
internal: bool = False

#: Use this to set the name of the function as exposed to python
#:
#: When applied to a constructor, creates a static method for the overload instead.
rename: Optional[str] = None

#: Mechanism to override individual parameters
Expand Down Expand Up @@ -212,7 +214,7 @@ def validate_overloads(cls, value):
def validate_virtual_xform(cls, v, values):
if v and values.get("trampoline_cpp_code"):
raise ValueError(
f"cannot specify trampoline_cpp_code and virtual_xform for the same method"
"cannot specify trampoline_cpp_code and virtual_xform for the same method"
)
return v

Expand All @@ -222,6 +224,8 @@ def validate_virtual_xform(cls, v, values):


class PropAccess(enum.Enum):
"""Whether a property is writable."""

#: Determine read/read-write automatically:
#:
#: * If a struct/union, default to readwrite
Expand Down
7 changes: 6 additions & 1 deletion tests/cpp/gen/ft/rename.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,15 @@ classes:
Param1:
rename: P1
methods:
OriginalClass:
overloads:
'':
int:
rename: new
fnOriginal:
rename: fnRenamed
fnRenamedParam:
param_override:
x:
name: y
setProp:
setProp:
5 changes: 4 additions & 1 deletion tests/cpp/rpytest/ft/include/rename.h
Original file line number Diff line number Diff line change
Expand Up @@ -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; }
Expand All @@ -37,4 +40,4 @@ struct OriginalClass {
// enums
enum OriginalEnum {
Original1 = 1
};
};
4 changes: 4 additions & 0 deletions tests/test_ft_rename.py
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand Down
Loading