Skip to content

Support ty = Any for arguments, return values, properties and out-params - #29

Open
Linklsk wants to merge 8 commits into
Sebekerga:mainfrom
Linklsk:feat/any-type
Open

Linklsk wants to merge 8 commits into
Sebekerga:mainfrom
Linklsk:feat/any-type

Conversation

@Linklsk

@Linklsk Linklsk commented Oct 7, 2026

Copy link
Copy Markdown

Adds ty = Any, mapping to ParamValue so that an argument, return value or property keeps whichever
1C type the platform sent.

Overlap with your feat/support-for-any-func-args-and-return

Same name, same idea, and expr_to_os_value comes out identical. The one substantive difference is
expr_from_os_value:

  • that branch yields &#expr
  • this one yields an owned #expr.clone()

set_prop_val generates self.<field> = <expr_from_os_value(...)>.into(), and there is no
From<&ParamValue> for ParamValue, so the reference version cannot compile for properties. Owning the
value is what makes writable Any properties work — that branch has no Any properties.

If you would rather merge your branch and take only the property support from here, the change is
confined to the Any arm of expr_from_os_value.

Everything else is additive: constants.rs, ParamType, FuncParamType, allowed_defaults.

This branch is based on the fixes PR, so it shows those commits until that one merges; I will rebase
afterwards.

Tests

tests/interface/any.rs is a new test target with 61 tests, deliberately separate from
tests/interface/functions.rs whose expectations are pinned to method indices. It covers every
ParamValue variant round-tripping through an Any argument, return value, property and out-parameter,
plus an Any default value.

Four new trybuild fixtures — any_type.rs under functions, result, out_params and defaults —
and Any properties added to the existing props.rs fixture.

cargo test --workspace — 145 passed, 0 failed.

Docs and sample

README: Any in the argument, return and property tables, a section on dynamic values, and an explicit
note that Native API supports neither VTYPE_INTERFACE nor VTYPE_VARIANT, so 1C objects cannot be
passed to a component at all.

Sample: DescribeValue / ОписатьЗначение reports the type it received and stores the value into a
LastValue / ПоследнееЗначение property.

Linklsk and others added 8 commits October 7, 2026 13:24
From<&TVariant> only handled Int32 and Double, silently turning VTYPE_I2, VTYPE_UI1, VTYPE_UI2, VTYPE_ERROR and VTYPE_R4 into ParamValue::Empty. Per the Native API docs the platform stores integers in lVal and fractions in dblVal regardless of the tag, so those are read now. Adds unit tests covering every tag.
Taken from upstream feat/support-for-any-func-args-and-return, where they accompany the Any feature but are independent of it: elide the lifetime on This::get_component, make ParamValues::iter lifetime explicit, and allow the unused name_override field. Clears three of the four pre-existing clippy warnings. Also corrects the os_string_nil doc comment on unix, which still claimed there is no terminator after the previous commit added one.
ComponentWrapper assumes destroy sits right after the four interface pointers, but in Component five fields were declared in between, so destroy landed at offset 96 on x86_64 and 48 on x86 while the wrapper read offset 32 and 16. That slot holds memory_manager_ptr, which set_mem_manager fills with a live pointer to the platform allocator, so DestroyObject called it as a function. 1C died with c0000005 and DEP flag 8 at an address belonging to no loaded module.

Move destroy up to the offset the wrapper expects and pin the layout with offset_of! assertions plus a create/destroy roundtrip test that runs on both x86_64 and i686.
A panic in add-in code used to unwind through the C++ frames of the platform, which aborts the process. Every callback in init_done, lang_extender, locale_base and user_lang_base now runs through a guard that catches it, reports it with AddError and returns the failure value the platform expects. set_mem_manager is left alone: it only copies a pointer.

The add-in state is unknown after unwinding, so the component is poisoned on the first panic and every later call returns the fallback without touching it.

init now stores connection_ptr before running add-in code. The field existed but was never populated, so the FFI layer had no way to reach AddError - which is also what makes a panic inside init itself reportable.

Adds AppCapabilities for the SetPlatformCapabilities negotiation and tests for the guard, the poisoning and the negotiation.
The platform withholds message output and platform info from components that do not negotiate capabilities, so Connection::add_error was a silent no-op. extern_functions! already generated a PLATFORM_CAPABILITIES static for this but never emitted the function that fills it.

The static loses its mut: AtomicI32 needs no unsafe access, and references to static mut become errors in edition 2024. Like the other four exports it uses extern C, which the x86 build confirms is the right convention for the DLL exports, while the vtable methods stay extern system.
ReportMessage pushes a line into the 1C message window through add_error, which only reaches the user now that capabilities are negotiated. Panic raises deliberately so the guard can be checked end to end; it poisons the component, so it has to be called last.

README documents the guard, the poisoning and the panic = abort caveat.
ParamValue already models a dynamic 1C value in the core, but the derive macro only accepted the six concrete types. Any maps to ParamValue itself, so expr_to_os_value and expr_from_os_value pass the value through instead of wrapping it in a ParamValue::X constructor. Defaults are allowed and take any ParamValue expression.

This overlaps feat/support-for-any-func-args-and-return, which adds the same type under the same name. The difference is expr_from_os_value: that branch yields a reference, and set_prop_val assigns .into() of it into the field, which needs From<&ParamValue> for ParamValue and does not compile. Yielding an owned value is what makes writable Any properties work; they are covered by tests/interface/any.rs together with args, returns, out-params and defaults.

Documents Any in the README tables, demonstrates it with DescribeValue and a LastValue property in the sample, and adds four trybuild fixtures plus Any properties to the existing one.
@Linklsk Linklsk closed this Oct 7, 2026
@Linklsk Linklsk reopened this Oct 15, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants