Skip to content

Return a MEOS struct as the struct, not as a pointer - #20

Merged
estebanzimanyi merged 1 commit into
MobilityDB:mainfrom
estebanzimanyi:fix/by-value-struct-returns
Sep 2, 2026
Merged

estebanzimanyi merged 1 commit into
MobilityDB:mainfrom
estebanzimanyi:fix/by-value-struct-returns

Conversation

@estebanzimanyi

Copy link
Copy Markdown
Member

Three MEOS functions hand a struct back by value — tpoint_as_mvtgeom
answers MvtGeom, tgeo_space_split answers SpaceSplit,
tgeo_space_time_split answers SpaceTimeSplit — and a struct return is not
a pointer. On the ABI these bindings ship for, a 24-byte struct comes back
through a hidden first argument the caller supplies, so a binding that
declares the return as a pointer shifts every real argument by one register
and the callee reads the second argument where the first belongs. Measured on
tpoint_as_mvtgeom over a temporal point and an STBox: with the return
declared void * the call answers
The temporal value must be a temporal point, MEOS validating the STBox it
receives in place of the temporal value, and with the return declared
MvtGeom the same call answers count=2 and two live pointers.

The C# form of such a struct comes from the catalog's own structs entry:
field for field, a pointer as IntPtr and a scalar through the same map the
parameters use, under [StructLayout(LayoutKind.Sequential)]. Only a struct a
function actually returns or takes by value gets one, which the generator
reads off the signatures rather than a list — every other MEOS struct crosses
the boundary as a pointer and stays opaque.

Two tests read every field of one. The MvtGeom test reads its geometry back
through geo_as_text and walks its times array for exactly count
increasing timestamps; the SpaceSplit test reads each fragment through
tspatial_as_text and each bin through geo_as_text. A field at the wrong
offset, or a call whose arguments shifted, answers neither.

Three MEOS functions hand a struct back by value — `tpoint_as_mvtgeom`
answers `MvtGeom`, `tgeo_space_split` answers `SpaceSplit`,
`tgeo_space_time_split` answers `SpaceTimeSplit` — and a struct return is not
a pointer. On the ABI these bindings ship for, a 24-byte struct comes back
through a hidden first argument the caller supplies, so a binding that
declares the return as a pointer shifts every real argument by one register
and the callee reads the second argument where the first belongs. Measured on
`tpoint_as_mvtgeom` over a temporal point and an STBox: with the return
declared `void *` the call answers
`The temporal value must be a temporal point`, MEOS validating the STBox it
receives in place of the temporal value, and with the return declared
`MvtGeom` the same call answers `count=2` and two live pointers.

The C# form of such a struct comes from the catalog's own `structs` entry:
field for field, a pointer as `IntPtr` and a scalar through the same map the
parameters use, under `[StructLayout(LayoutKind.Sequential)]`. Only a struct a
function actually returns or takes by value gets one, which the generator
reads off the signatures rather than a list — every other MEOS struct crosses
the boundary as a pointer and stays opaque.

Two tests read every field of one. The MvtGeom test reads its geometry back
through `geo_as_text` and walks its `times` array for exactly `count`
increasing timestamps; the SpaceSplit test reads each fragment through
`tspatial_as_text` and each bin through `geo_as_text`. A field at the wrong
offset, or a call whose arguments shifted, answers neither.
@estebanzimanyi
estebanzimanyi merged commit e4af5ca into MobilityDB:main Sep 2, 2026
1 check passed
@estebanzimanyi
estebanzimanyi deleted the fix/by-value-struct-returns branch September 2, 2026 21:09
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.

1 participant