diff --git a/MEOS.NET.Tests/UntypedAndVoidTests.cs b/MEOS.NET.Tests/UntypedAndVoidTests.cs
new file mode 100644
index 0000000..dade7df
--- /dev/null
+++ b/MEOS.NET.Tests/UntypedAndVoidTests.cs
@@ -0,0 +1,45 @@
+using MEOS.NET.Enums;
+using MEOS.NET.Types;
+
+namespace MEOS.NET.Tests
+{
+ ///
+ /// A method MEOS states nothing about the pointee of, and a method that
+ /// answers nothing, are both methods: the first takes the pointer of the
+ /// value the caller means, the second is called for what it does.
+ ///
+ [TestClass]
+ public class UntypedAndVoidTests : MeosTest
+ {
+ [TestMethod]
+ public void AnIndexTakesTheSpansItIsGivenAsPointers()
+ {
+ RTree? tree = RTree.CreateFloatspan();
+
+ Assert.IsNotNull(tree);
+
+ Span first = FloatSpan.In("[1, 3]")!;
+ Span second = FloatSpan.In("[8, 10]")!;
+
+ Assert.IsTrue(tree!.Insert(first.Ptr, 1));
+ Assert.IsTrue(tree.Insert(second.Ptr, 2));
+
+ MeosArray? found = MeosArray.Create(8);
+
+ Assert.IsNotNull(found);
+ Assert.AreEqual(1, tree.Search(IndexSearchOp.IndexOverlaps, second.Ptr, found!));
+ }
+
+ [TestMethod]
+ public void ClearingTheSchemaCacheIsAMethodThatAnswersNothing()
+ {
+ // `meos_pc_schema_clear()` answers nothing and is called for what
+ // it does; a cleared cache holds no schema, and MEOS says so by
+ // raising rather than by answering null.
+ Pcschema.Clear();
+
+ Assert.ThrowsException(
+ () => Pcschema.Get(1));
+ }
+ }
+}
diff --git a/MEOS.NET/Types/MeosArray.g.cs b/MEOS.NET/Types/MeosArray.g.cs
index 2d788b1..63e2137 100644
--- a/MEOS.NET/Types/MeosArray.g.cs
+++ b/MEOS.NET/Types/MeosArray.g.cs
@@ -14,6 +14,9 @@ public class MeosArray : Value
{
internal MeosArray(IntPtr ptr) : base(ptr) { }
+ public void Add(IntPtr value)
+ => Meos.MeosArrayAdd(this.Ptr, value);
+
public int Count()
=> Meos.MeosArrayCount(this.Ptr);
@@ -23,6 +26,9 @@ public void Destroy()
public void DestroyFree()
=> Meos.MeosArrayDestroyFree(this.Ptr);
+ public IntPtr Get(int n)
+ => Meos.MeosArrayGet(this.Ptr, n);
+
public void Reset()
=> Meos.MeosArrayReset(this.Ptr);
diff --git a/MEOS.NET/Types/Pcschema.g.cs b/MEOS.NET/Types/Pcschema.g.cs
index 47db74e..be37d5f 100644
--- a/MEOS.NET/Types/Pcschema.g.cs
+++ b/MEOS.NET/Types/Pcschema.g.cs
@@ -14,6 +14,9 @@ public class Pcschema : Value
{
internal Pcschema(IntPtr ptr) : base(ptr) { }
+ public static void Clear()
+ => Meos.MeosPcSchemaClear();
+
public static string? Compression(uint pcid)
=> Meos.MeosPcSchemaCompression(pcid);
@@ -23,6 +26,12 @@ internal Pcschema(IntPtr ptr) : base(ptr) { }
public static int Ndims(uint pcid)
=> Meos.MeosPcSchemaNdims(pcid);
+ public static void Register(uint pcid, Pcschema schema)
+ => Meos.MeosPcSchemaRegister(pcid, schema.Ptr);
+
+ public static void RegisterXml(uint pcid, Pcschema schema, string xml_text)
+ => Meos.MeosPcSchemaRegisterXml(pcid, schema.Ptr, xml_text);
+
public static int SRID(uint pcid)
=> Meos.MeosPcSchemaSrid(pcid);
diff --git a/MEOS.NET/Types/RTree.g.cs b/MEOS.NET/Types/RTree.g.cs
index 3d5b026..3ea0ab9 100644
--- a/MEOS.NET/Types/RTree.g.cs
+++ b/MEOS.NET/Types/RTree.g.cs
@@ -20,6 +20,9 @@ public void Free()
public int Height()
=> Meos.RtreeHeight(this.Ptr);
+ public bool Insert(IntPtr box, long id)
+ => Meos.RtreeInsert(this.Ptr, box, id);
+
public bool InsertTemporal(Temporal temp, long id)
=> Meos.RtreeInsertTemporal(this.Ptr, temp.Ptr, id);
@@ -29,12 +32,28 @@ public bool InsertTemporalSplit(Temporal temp, long id, int maxboxes)
public int Join(RTree rtree2, IndexSearchOp op, MeosArray result)
=> Meos.RtreeJoin(this.Ptr, rtree2.Ptr, (int) op, result.Ptr);
+ public bool Load(IntPtr boxes, long[] ids)
+ {
+ GCHandle _ids = GCHandle.Alloc(ids, GCHandleType.Pinned);
+ try
+ {
+ return Meos.RtreeLoad(this.Ptr, boxes, _ids.AddrOfPinnedObject(), ids.Length);
+ }
+ finally
+ {
+ _ids.Free();
+ }
+ }
+
public long MemSize()
=> Meos.RtreeMemSize(this.Ptr);
public int NumEntries()
=> Meos.RtreeNumEntries(this.Ptr);
+ public int Search(IndexSearchOp op, IntPtr query, MeosArray result)
+ => Meos.RtreeSearch(this.Ptr, (int) op, query, result.Ptr);
+
public int SearchTemporal(IndexSearchOp op, Temporal temp, MeosArray result)
=> Meos.RtreeSearchTemporal(this.Ptr, (int) op, temp.Ptr, result.Ptr);
diff --git a/MEOS.NET/Types/SPTree.g.cs b/MEOS.NET/Types/SPTree.g.cs
index 96b211b..f10ab9a 100644
--- a/MEOS.NET/Types/SPTree.g.cs
+++ b/MEOS.NET/Types/SPTree.g.cs
@@ -20,6 +20,9 @@ public void Free()
public int Height()
=> Meos.SptreeHeight(this.Ptr);
+ public bool Insert(IntPtr box, long id)
+ => Meos.SptreeInsert(this.Ptr, box, id);
+
public bool InsertTemporal(Temporal temp, long id)
=> Meos.SptreeInsertTemporal(this.Ptr, temp.Ptr, id);
@@ -29,12 +32,28 @@ public bool InsertTemporalSplit(Temporal temp, long id, int maxboxes)
public int Join(SPTree sptree2, IndexSearchOp op, MeosArray result)
=> Meos.SptreeJoin(this.Ptr, sptree2.Ptr, (int) op, result.Ptr);
+ public bool Load(IntPtr boxes, long[] ids)
+ {
+ GCHandle _ids = GCHandle.Alloc(ids, GCHandleType.Pinned);
+ try
+ {
+ return Meos.SptreeLoad(this.Ptr, boxes, _ids.AddrOfPinnedObject(), ids.Length);
+ }
+ finally
+ {
+ _ids.Free();
+ }
+ }
+
public long MemSize()
=> Meos.SptreeMemSize(this.Ptr);
public int NumEntries()
=> Meos.SptreeNumEntries(this.Ptr);
+ public int Search(IndexSearchOp op, IntPtr query, MeosArray result)
+ => Meos.SptreeSearch(this.Ptr, (int) op, query, result.Ptr);
+
public int SearchTemporal(IndexSearchOp op, Temporal temp, MeosArray result)
=> Meos.SptreeSearchTemporal(this.Ptr, (int) op, temp.Ptr, result.Ptr);
diff --git a/tools/objectgen.py b/tools/objectgen.py
index 95f5ac9..1fc3856 100644
--- a/tools/objectgen.py
+++ b/tools/objectgen.py
@@ -338,6 +338,8 @@ def map_return(self, f: dict, wrapper_ret: str) -> tuple[str, str] | None:
return (f"{elem}?[]", f"MEOSFactory.Wrap{elem}Array($)")
if wrapper_ret in ("long[]", "int[]", "double[]", "byte[]"):
return (wrapper_ret, "$")
+ if c == "void *" and wrapper_ret == "IntPtr":
+ return ("IntPtr", "$")
struct = self.value_struct(c)
if struct and wrapper_ret == "IntPtr":
return (f"{struct}?", f"MEOSConvert.ToStruct<{struct}>($)")
@@ -389,6 +391,13 @@ def map_param(self, c_type: str, cs_type: str, name: str) -> tuple[str, str] | N
cls = self.m.class_for_ctype(c)
if cls and cs_type == "IntPtr":
return (cls, f"{name}.Ptr")
+ # An UNTYPED pointer stays untyped: MEOS states nothing about what it
+ # points at, so the layer states nothing either and the caller hands
+ # over the pointer of the value it means — the `Ptr` every wrapped
+ # instance publishes. GoMEOS answers the same shape with
+ # `unsafe.Pointer`.
+ if c == "void *" and cs_type == "IntPtr":
+ return ("IntPtr", name)
struct = self.value_struct(c)
if struct and cs_type == "IntPtr":
return (struct, scratch(name))
@@ -468,9 +477,6 @@ def method_for(self, cls: str, entry: dict) -> Method | None:
f"{oo}: return {clean(f['returnType']['c'])} needs wrapping")
return None
ret_type, ret_expr = ret
- if static and ret_type == "void":
- self.deferred[cls].append(f"{oo}: neither a receiver nor a value to return")
- return None
# The length is the array's own, so it leaves the C# signature.
count_of = {codegen.csharp_param_name(a["lengthFrom"]["name"]):